Make WayVR IPC independent of the built-in Wayland server

- Rename state -> wayland_state
- Move WayVR IPC server outside "wayvr" (wayland server) feature
- WayVR IPC server is now available without "wayvr" (wayland server) feature
- Remove run_compositor_at_start (run wayland server instantly)
This commit is contained in:
Aleksander
2025-12-23 23:35:00 +01:00
committed by galister
parent 5afe85a3b3
commit 36576122a9
18 changed files with 387 additions and 328 deletions

View File

@@ -17,7 +17,8 @@ members = [
"wlx-overlay-s", "wlx-overlay-s",
"wlx-capture", "wlx-capture",
"dash-frontend", "dash-frontend",
"wayvr-ipc", "wayvrctl", "wayvr-ipc",
"wayvrctl",
] ]
resolver = "3" resolver = "3"

View File

@@ -382,7 +382,7 @@ impl Layout {
let mut iter = |idx: usize| -> anyhow::Result<bool> { let mut iter = |idx: usize| -> anyhow::Result<bool> {
let child_id = self.state.tree.get_child_id(parent_node_id, idx); let child_id = self.state.tree.get_child_id(parent_node_id, idx);
self.push_event_widget(child_id, event, event_result, alterables, user_data, false)?; self.push_event_widget(child_id, event, event_result, alterables, user_data)?;
Ok(!event_result.can_propagate()) Ok(!event_result.can_propagate())
}; };
@@ -403,7 +403,6 @@ impl Layout {
event_result: &mut EventResult, event_result: &mut EventResult,
alterables: &mut EventAlterables, alterables: &mut EventAlterables,
user_data: &mut (&'a mut U1, &'a mut U2), user_data: &mut (&'a mut U1, &'a mut U2),
is_root_node: bool,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let l = self.state.tree.layout(node_id)?; let l = self.state.tree.layout(node_id)?;
let Some(widget_id) = self.state.tree.get_node_context(node_id).copied() else { let Some(widget_id) = self.state.tree.get_node_context(node_id).copied() else {
@@ -495,7 +494,6 @@ impl Layout {
&mut event_result, &mut event_result,
&mut alterables, &mut alterables,
&mut (user1, user2), &mut (user1, user2),
true,
)?; )?;
self.process_alterables(alterables)?; self.process_alterables(alterables)?;
Ok(event_result) Ok(event_result)

View File

@@ -81,9 +81,11 @@ tracing = "0.1.43"
vulkano = { workspace = true } vulkano = { workspace = true }
vulkano-shaders = { workspace = true } vulkano-shaders = { workspace = true }
wgui = { path = "../wgui" } wgui = { path = "../wgui" }
bytes = { version = "1.11.0" }
wayvr-ipc = { path = "../wayvr-ipc", default-features = false }
################################ ################################
#WayVR-only deps # Wayland Server deps
################################ ################################
khronos-egl = { version = "6.0.0", features = ["static"], optional = true } khronos-egl = { version = "6.0.0", features = ["static"], optional = true }
smithay = { version = "0.7.0", default-features = false, features = [ smithay = { version = "0.7.0", default-features = false, features = [
@@ -96,8 +98,6 @@ smithay = { version = "0.7.0", default-features = false, features = [
uuid = { version = "1.19.0", features = ["v4", "fast-rng"], optional = true } uuid = { version = "1.19.0", features = ["v4", "fast-rng"], optional = true }
wayland-client = { workspace = true, optional = true } wayland-client = { workspace = true, optional = true }
wayland-egl = { version = "0.32.8", optional = true } wayland-egl = { version = "0.32.8", optional = true }
bytes = { version = "1.11.0", optional = true }
wayvr-ipc = { path = "../wayvr-ipc", default-features = false, optional = true }
rust-embed = { workspace = true } rust-embed = { workspace = true }
signal-hook = "0.3.18" signal-hook = "0.3.18"
################################ ################################
@@ -105,6 +105,7 @@ signal-hook = "0.3.18"
[build-dependencies] [build-dependencies]
regex = { version = "1.12.2" } regex = { version = "1.12.2" }
# TODO: rename "wayvr" feature to "wayland-server"
[features] [features]
default = ["openvr", "openxr", "osc", "x11", "wayland", "wayvr"] default = ["openvr", "openxr", "osc", "x11", "wayland", "wayvr"]
openvr = ["dep:ovr_overlay", "dep:json"] openvr = ["dep:ovr_overlay", "dep:json"]
@@ -121,7 +122,5 @@ wayvr = [
"dep:uuid", "dep:uuid",
"dep:wayland-client", "dep:wayland-client",
"dep:wayland-egl", "dep:wayland-egl",
"dep:bytes",
"dep:wayvr-ipc",
] ]
as-raw-xcb-connection = [] as-raw-xcb-connection = []

View File

@@ -303,11 +303,10 @@ pub fn openvr_run(show_by_default: bool, headless: bool) -> Result<(), BackendEr
let _ = sender.send_params(&overlays, &app.input_state.devices); let _ = sender.send_params(&overlays, &app.input_state.devices);
} }
#[cfg(feature = "wayvr")]
if let Err(e) = if let Err(e) =
crate::overlays::wayvr::tick_events::<OpenVrOverlayData>(&mut app, &mut overlays) crate::ipc::events::tick_events::<OpenVrOverlayData>(&mut app, &mut overlays)
{ {
log::error!("WayVR tick_events failed: {e:?}"); log::error!("WayVR IPC tick_events failed: {e:?}");
} }
log::trace!("Rendering frame"); log::trace!("Rendering frame");
@@ -336,9 +335,7 @@ pub fn openvr_run(show_by_default: bool, headless: bool) -> Result<(), BackendEr
.for_each(|o| o.after_render(universe.clone(), &mut overlay_mgr, &app.gfx)); .for_each(|o| o.after_render(universe.clone(), &mut overlay_mgr, &app.gfx));
#[cfg(feature = "wayvr")] #[cfg(feature = "wayvr")]
if let Some(wayvr) = &app.wayvr { app.wayvr.borrow_mut().data.tick_finish()?;
wayvr.borrow_mut().data.tick_finish()?;
}
// chaperone // chaperone
} // main_loop } // main_loop

View File

@@ -373,9 +373,9 @@ pub fn openxr_run(show_by_default: bool, headless: bool) -> Result<(), BackendEr
#[cfg(feature = "wayvr")] #[cfg(feature = "wayvr")]
if let Err(e) = if let Err(e) =
crate::overlays::wayvr::tick_events::<OpenXrOverlayData>(&mut app, &mut overlays) crate::ipc::events::tick_events::<OpenXrOverlayData>(&mut app, &mut overlays)
{ {
log::error!("WayVR tick_events failed: {e:?}"); log::error!("WayVR IPC tick_events failed: {e:?}");
} }
// Begin rendering // Begin rendering
@@ -459,9 +459,7 @@ pub fn openxr_run(show_by_default: bool, headless: bool) -> Result<(), BackendEr
// End layer composition // End layer composition
#[cfg(feature = "wayvr")] #[cfg(feature = "wayvr")]
if let Some(wayvr) = &app.wayvr { app.wayvr.borrow_mut().data.tick_finish()?;
wayvr.borrow_mut().data.tick_finish()?;
}
// Begin layer submit // Begin layer submit
layers.sort_by(|a, b| b.0.total_cmp(&a.0)); layers.sort_by(|a, b| b.0.total_cmp(&a.0));

View File

@@ -37,8 +37,9 @@ use wayland_server::Client;
use wayland_server::backend::{ClientData, ClientId, DisconnectReason}; use wayland_server::backend::{ClientData, ClientId, DisconnectReason};
use wayland_server::protocol::wl_surface::WlSurface; use wayland_server::protocol::wl_surface::WlSurface;
use crate::ipc::event_queue::SyncEventQueue;
use super::WayVRTask; use super::WayVRTask;
use super::event_queue::SyncEventQueue;
pub struct Application { pub struct Application {
pub gles_renderer: GlesRenderer, pub gles_renderer: GlesRenderer,

View File

@@ -17,12 +17,13 @@ use smithay::{
use wayvr_ipc::packet_server; use wayvr_ipc::packet_server;
use crate::{ use crate::{
backend::wayvr::time::get_millis, gen_id, subsystem::hid::WheelDelta, windowing::OverlayID, backend::wayvr::time::get_millis, gen_id, ipc::event_queue::SyncEventQueue,
subsystem::hid::WheelDelta, windowing::OverlayID,
}; };
use super::{ use super::{
BlitMethod, WayVRSignal, client::WayVRCompositor, comp::send_frames_surface_tree, egl_data, BlitMethod, WayVRSignal, client::WayVRCompositor, comp::send_frames_surface_tree, egl_data,
event_queue::SyncEventQueue, process, smithay_wrapper, time, window, process, smithay_wrapper, time, window,
}; };
fn generate_auth_key() -> String { fn generate_auth_key() -> String {

View File

@@ -3,20 +3,16 @@ mod comp;
pub mod display; pub mod display;
pub mod egl_data; pub mod egl_data;
mod egl_ex; mod egl_ex;
pub mod event_queue;
mod handle; mod handle;
mod process; pub mod process;
pub mod server_ipc;
mod smithay_wrapper; mod smithay_wrapper;
mod time; mod time;
mod window; pub mod window;
use anyhow::Context; use anyhow::Context;
use comp::Application; use comp::Application;
use display::{Display, DisplayInitParams, DisplayVec}; use display::{Display, DisplayInitParams, DisplayVec};
use event_queue::SyncEventQueue;
use process::ProcessVec; use process::ProcessVec;
use serde::Deserialize; use serde::Deserialize;
use server_ipc::WayVRServer;
use smallvec::SmallVec; use smallvec::SmallVec;
use smithay::{ use smithay::{
backend::{ backend::{
@@ -48,6 +44,7 @@ use wayvr_ipc::{
use xkbcommon::xkb; use xkbcommon::xkb;
use crate::{ use crate::{
ipc::{event_queue::SyncEventQueue, ipc_server, signal::WayVRSignal},
state::AppState, state::AppState,
subsystem::hid::{MODS_TO_KEYS, WheelDelta}, subsystem::hid::{MODS_TO_KEYS, WheelDelta},
}; };
@@ -87,19 +84,6 @@ pub enum WayVRTask {
ProcessTerminationRequest(process::ProcessHandle), ProcessTerminationRequest(process::ProcessHandle),
} }
#[derive(Clone)]
pub enum WayVRSignal {
DisplayVisibility(display::DisplayHandle, bool),
DisplayWindowLayout(
display::DisplayHandle,
packet_server::WvrDisplayWindowLayout,
),
BroadcastStateChanged(packet_server::WvrStateChanged),
DropOverlay(crate::windowing::OverlayID),
Haptics(super::input::Haptics),
CustomTask(crate::backend::task::ModifyPanelTask),
}
pub enum BlitMethod { pub enum BlitMethod {
Dmabuf, Dmabuf,
Software, Software,
@@ -127,20 +111,19 @@ pub struct WayVRState {
time_start: u64, time_start: u64,
pub displays: display::DisplayVec, pub displays: display::DisplayVec,
pub manager: client::WayVRCompositor, pub manager: client::WayVRCompositor,
wm: Rc<RefCell<window::WindowManager>>, pub wm: Rc<RefCell<window::WindowManager>>,
egl_data: Rc<egl_data::EGLData>, egl_data: Rc<egl_data::EGLData>,
pub processes: process::ProcessVec, pub processes: process::ProcessVec,
pub config: Config, pub config: Config,
dashboard_display: Option<display::DisplayHandle>, dashboard_display: Option<display::DisplayHandle>,
pub tasks: SyncEventQueue<WayVRTask>, pub tasks: SyncEventQueue<WayVRTask>,
pub signals: SyncEventQueue<WayVRSignal>,
ticks: u64, ticks: u64,
cur_modifiers: u8, cur_modifiers: u8,
signals: SyncEventQueue<WayVRSignal>,
} }
pub struct WayVR { pub struct WayVR {
pub state: WayVRState, pub state: WayVRState,
pub ipc_server: WayVRServer,
} }
pub enum MouseIndex { pub enum MouseIndex {
@@ -159,7 +142,7 @@ pub enum TickTask {
impl WayVR { impl WayVR {
#[allow(clippy::too_many_lines, clippy::cognitive_complexity)] #[allow(clippy::too_many_lines, clippy::cognitive_complexity)]
pub fn new(config: Config) -> anyhow::Result<Self> { pub fn new(config: Config, signals: SyncEventQueue<WayVRSignal>) -> anyhow::Result<Self> {
log::info!("Initializing WayVR"); log::info!("Initializing WayVR");
let display: wayland_server::Display<Application> = wayland_server::Display::new()?; let display: wayland_server::Display<Application> = wayland_server::Display::new()?;
let dh = display.handle(); let dh = display.handle();
@@ -264,8 +247,6 @@ impl WayVR {
let time_start = get_millis(); let time_start = get_millis();
let ipc_server = WayVRServer::new()?;
let state = WayVRState { let state = WayVRState {
time_start, time_start,
manager: client::WayVRCompositor::new(state, display, seat_keyboard, seat_pointer)?, manager: client::WayVRCompositor::new(state, display, seat_keyboard, seat_pointer)?,
@@ -277,11 +258,11 @@ impl WayVR {
dashboard_display: None, dashboard_display: None,
ticks: 0, ticks: 0,
tasks, tasks,
signals: SyncEventQueue::new(),
cur_modifiers: 0, cur_modifiers: 0,
signals,
}; };
Ok(Self { state, ipc_server }) Ok(Self { state })
} }
pub fn render_display(&mut self, display: display::DisplayHandle) -> anyhow::Result<bool> { pub fn render_display(&mut self, display: display::DisplayHandle) -> anyhow::Result<bool> {
@@ -312,13 +293,14 @@ impl WayVR {
} }
#[allow(clippy::too_many_lines, clippy::cognitive_complexity)] #[allow(clippy::too_many_lines, clippy::cognitive_complexity)]
pub fn tick_events(&mut self, app: &AppState) -> anyhow::Result<Vec<TickTask>> { pub fn tick_events(&mut self, app: &mut AppState) -> anyhow::Result<Vec<TickTask>> {
let mut tasks: Vec<TickTask> = Vec::new(); let mut tasks: Vec<TickTask> = Vec::new();
self.ipc_server.tick(&mut server_ipc::TickParams { app.ipc_server.tick(&mut ipc_server::TickParams {
state: &mut self.state, wayland_state: &mut self.state,
input_state: &app.input_state,
tasks: &mut tasks, tasks: &mut tasks,
app, signals: &app.wayvr_signals,
}); });
// Check for redraw events // Check for redraw events
@@ -357,11 +339,11 @@ impl WayVR {
} }
for (handle, display) in self.state.displays.iter_mut() { for (handle, display) in self.state.displays.iter_mut() {
display.tick(&self.state.config, &handle, &mut self.state.signals); display.tick(&self.state.config, &handle, &mut app.wayvr_signals);
} }
if !to_remove.is_empty() { if !to_remove.is_empty() {
self.state.signals.send(WayVRSignal::BroadcastStateChanged( app.wayvr_signals.send(WayVRSignal::BroadcastStateChanged(
packet_server::WvrStateChanged::ProcessRemoved, packet_server::WvrStateChanged::ProcessRemoved,
)); ));
} }
@@ -402,7 +384,7 @@ impl WayVR {
}; };
display.add_window(window_handle, process_handle, &toplevel); display.add_window(window_handle, process_handle, &toplevel);
self.state.signals.send(WayVRSignal::BroadcastStateChanged( app.wayvr_signals.send(WayVRSignal::BroadcastStateChanged(
packet_server::WvrStateChanged::WindowCreated, packet_server::WvrStateChanged::WindowCreated,
)); ));
} }

View File

@@ -19,6 +19,7 @@ use crate::{
}, },
config::load_config_with_conf_d, config::load_config_with_conf_d,
config_io, config_io,
ipc::{event_queue::SyncEventQueue, signal::WayVRSignal},
overlays::wayvr::{WayVRData, executable_exists_in_path}, overlays::wayvr::{WayVRData, executable_exists_in_path},
}; };
@@ -135,9 +136,6 @@ pub struct WayVRDashboard {
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
pub struct WayVRConfig { pub struct WayVRConfig {
#[serde(default = "def_true")]
pub run_compositor_at_start: bool,
#[serde(default = "Default::default")] #[serde(default = "Default::default")]
pub catalogs: HashMap<String, WayVRCatalog>, pub catalogs: HashMap<String, WayVRCatalog>,
@@ -203,7 +201,8 @@ impl WayVRConfig {
&self, &self,
config: &GeneralConfig, config: &GeneralConfig,
tasks: &mut TaskContainer, tasks: &mut TaskContainer,
) -> anyhow::Result<Option<Rc<RefCell<WayVRData>>>> { signals: SyncEventQueue<WayVRSignal>,
) -> anyhow::Result<Rc<RefCell<WayVRData>>> {
let primary_count = self let primary_count = self
.displays .displays
.iter() .iter()
@@ -212,10 +211,6 @@ impl WayVRConfig {
if primary_count > 1 { if primary_count > 1 {
anyhow::bail!("Number of primary displays is more than 1") anyhow::bail!("Number of primary displays is more than 1")
} else if primary_count == 0 {
log::warn!(
"No primary display specified. External Wayland applications will not be attached."
);
} }
for (catalog_name, catalog) in &self.catalogs { for (catalog_name, catalog) in &self.catalogs {
@@ -231,15 +226,10 @@ impl WayVRConfig {
} }
} }
if self.run_compositor_at_start { Ok(Rc::new(RefCell::new(WayVRData::new(
// Start Wayland server instantly Self::get_wayvr_config(config, self)?,
Ok(Some(Rc::new(RefCell::new(WayVRData::new( signals,
Self::get_wayvr_config(config, self)?, )?)))
)?))))
} else {
// Lazy-init WayVR later if the user requested
Ok(None)
}
} }
} }

View File

@@ -0,0 +1,189 @@
use std::{cell::RefCell, rc::Rc};
use crate::ipc::ipc_server;
use wayvr_ipc::packet_server;
#[cfg(feature = "wayvr")]
use crate::{
backend::wayvr, config_wayvr, overlays::wayvr::OverlayToCreate, overlays::wayvr::WayVRData,
};
use crate::{
backend::{
self,
task::{OverlayTask, TaskType},
},
ipc::signal::WayVRSignal,
overlays::{self},
state::AppState,
windowing::{OverlaySelector, manager::OverlayWindowManager},
};
#[cfg(feature = "wayvr")]
fn process_tick_tasks(
app: &mut AppState,
tick_tasks: Vec<backend::wayvr::TickTask>,
r_wayvr: &Rc<RefCell<WayVRData>>,
) -> anyhow::Result<()> {
for tick_task in tick_tasks {
match tick_task {
backend::wayvr::TickTask::NewExternalProcess(request) => {
let config = &app.session.wayvr_config;
let disp_name = request.env.display_name.map_or_else(
|| {
config
.get_default_display()
.map(|(display_name, _)| display_name)
},
|display_name| {
config
.get_display(display_name.as_str())
.map(|_| display_name)
},
);
if let Some(disp_name) = disp_name {
let mut wayvr = r_wayvr.borrow_mut();
log::info!("Registering external process with PID {}", request.pid);
let disp_handle = overlays::wayvr::get_or_create_display_by_name(
app, &mut wayvr, &disp_name,
)?;
wayvr
.data
.state
.add_external_process(disp_handle, request.pid);
wayvr
.data
.state
.manager
.add_client(wayvr::client::WayVRClient {
client: request.client,
display_handle: disp_handle,
pid: request.pid,
});
}
}
wayvr::TickTask::NewDisplay(cpar, disp_handle) => {
log::info!("Creating new display with name \"{}\"", cpar.name);
let mut wayvr = r_wayvr.borrow_mut();
let unique_name = wayvr.get_unique_display_name(cpar.name);
let disp_handle = match disp_handle {
Some(d) => d,
None => wayvr.data.state.create_display(
cpar.width,
cpar.height,
&unique_name,
false,
)?,
};
wayvr.overlays_to_create.push(OverlayToCreate {
disp_handle,
conf_display: config_wayvr::WayVRDisplay {
attach_to: Some(config_wayvr::AttachTo::from_packet(&cpar.attach_to)),
width: cpar.width,
height: cpar.height,
pos: None,
primary: None,
rotation: None,
scale: cpar.scale,
},
});
}
}
}
Ok(())
}
#[allow(clippy::too_many_lines)]
pub fn tick_events<O>(
app: &mut AppState,
overlays: &mut OverlayWindowManager<O>,
) -> anyhow::Result<()>
where
O: Default,
{
#[cfg(feature = "wayvr")]
let r_wayvr = app.wayvr.clone();
#[cfg(feature = "wayvr")]
let mut wayvr = r_wayvr.borrow_mut();
while let Some(signal) = app.wayvr_signals.read() {
match signal {
#[cfg(feature = "wayvr")]
WayVRSignal::DisplayVisibility(display_handle, visible) => {
if let Some(overlay_id) = wayvr.display_handle_map.get(&display_handle) {
let overlay_id = *overlay_id;
wayvr
.data
.state
.set_display_visible(display_handle, visible);
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Modify(
OverlaySelector::Id(overlay_id),
Box::new(move |app, o| {
if visible == o.is_active() {
return;
}
if visible {
o.activate(app);
} else {
o.deactivate();
}
}),
)));
}
}
#[cfg(feature = "wayvr")]
WayVRSignal::DisplayWindowLayout(display_handle, layout) => {
wayvr.data.state.set_display_layout(display_handle, layout);
}
#[cfg(feature = "wayvr")]
WayVRSignal::BroadcastStateChanged(packet) => {
app.ipc_server
.broadcast(packet_server::PacketServer::WvrStateChanged(packet));
}
#[cfg(feature = "wayvr")]
WayVRSignal::Haptics(haptics) => {
wayvr.pending_haptics = Some(haptics);
}
WayVRSignal::DropOverlay(overlay_id) => {
app.tasks
.enqueue(TaskType::Overlay(OverlayTask::Drop(OverlaySelector::Id(
overlay_id,
))));
}
WayVRSignal::CustomTask(custom_task) => {
app.tasks
.enqueue(TaskType::Overlay(OverlayTask::ModifyPanel(custom_task)));
}
}
}
#[cfg(feature = "wayvr")]
{
let tick_tasks = wayvr.data.tick_events(app)?;
process_tick_tasks(app, tick_tasks, &r_wayvr)?;
}
#[cfg(not(feature = "wayvr"))]
{
app.ipc_server.tick(&mut ipc_server::TickParams {
input_state: &app.input_state,
signals: &app.wayvr_signals,
});
}
#[cfg(feature = "wayvr")]
overlays::wayvr::create_queued_displays(app, &mut wayvr, overlays)?;
Ok(())
}

View File

@@ -1,6 +1,10 @@
use crate::state::AppState; #[cfg(feature = "wayvr")]
use crate::backend::wayvr::{self, WayVRState};
use super::{TickTask, WayVRSignal, display, process, window}; use crate::{
backend::input::InputState,
ipc::{event_queue::SyncEventQueue, signal::WayVRSignal},
};
use bytes::BufMut; use bytes::BufMut;
use glam::Vec3A; use glam::Vec3A;
use interprocess::local_socket::{self, ToNsName, traits::Listener}; use interprocess::local_socket::{self, ToNsName, traits::Listener};
@@ -71,9 +75,12 @@ fn read_payload(conn: &mut local_socket::Stream, size: u32) -> Option<Payload> {
} }
pub struct TickParams<'a> { pub struct TickParams<'a> {
pub state: &'a mut super::WayVRState, #[cfg(feature = "wayvr")]
pub tasks: &'a mut Vec<TickTask>, pub wayland_state: &'a mut WayVRState,
pub app: &'a AppState, #[cfg(feature = "wayvr")]
pub tasks: &'a mut Vec<wayvr::TickTask>,
pub signals: &'a SyncEventQueue<WayVRSignal>,
pub input_state: &'a InputState,
} }
pub fn gen_args_vec(input: &str) -> Vec<&str> { pub fn gen_args_vec(input: &str) -> Vec<&str> {
@@ -149,13 +156,14 @@ impl Connection {
Ok(()) Ok(())
} }
#[cfg(feature = "wayvr")]
fn handle_wvr_display_list( fn handle_wvr_display_list(
&mut self, &mut self,
params: &TickParams, params: &TickParams,
serial: ipc::Serial, serial: ipc::Serial,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let list: Vec<packet_server::WvrDisplay> = params let list: Vec<packet_server::WvrDisplay> = params
.state .wayland_state
.displays .displays
.vec .vec
.iter() .iter()
@@ -165,7 +173,10 @@ impl Connection {
return None; return None;
}; };
let display = &cell.obj; let display = &cell.obj;
Some(display.as_packet(display::DisplayHandle::new(idx as u32, cell.generation))) Some(display.as_packet(wayvr::display::DisplayHandle::new(
idx as u32,
cell.generation,
)))
}) })
.collect(); .collect();
@@ -185,8 +196,6 @@ impl Connection {
params: &TickParams, params: &TickParams,
serial: ipc::Serial, serial: ipc::Serial,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let input_state = &params.app.input_state;
let to_arr = |vec: &Vec3A| -> [f32; 3] { [vec.x, vec.y, vec.z] }; let to_arr = |vec: &Vec3A| -> [f32; 3] { [vec.x, vec.y, vec.z] };
send_packet( send_packet(
@@ -194,12 +203,12 @@ impl Connection {
&ipc::data_encode(&PacketServer::WlxInputStateResponse( &ipc::data_encode(&PacketServer::WlxInputStateResponse(
serial, serial,
packet_server::WlxInputState { packet_server::WlxInputState {
hmd_pos: to_arr(&input_state.hmd.translation), hmd_pos: to_arr(&params.input_state.hmd.translation),
left: WlxInputStatePointer { left: WlxInputStatePointer {
pos: to_arr(&input_state.pointers[0].raw_pose.translation), pos: to_arr(&params.input_state.pointers[0].raw_pose.translation),
}, },
right: WlxInputStatePointer { right: WlxInputStatePointer {
pos: to_arr(&input_state.pointers[0].raw_pose.translation), pos: to_arr(&params.input_state.pointers[0].raw_pose.translation),
}, },
}, },
)), )),
@@ -208,22 +217,24 @@ impl Connection {
Ok(()) Ok(())
} }
#[cfg(feature = "wayvr")]
fn handle_wvr_display_create( fn handle_wvr_display_create(
&mut self, &mut self,
params: &mut TickParams, params: &mut TickParams,
serial: ipc::Serial, serial: ipc::Serial,
packet_params: packet_client::WvrDisplayCreateParams, packet_params: packet_client::WvrDisplayCreateParams,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let display_handle = params.state.create_display( let display_handle = params.wayland_state.create_display(
packet_params.width, packet_params.width,
packet_params.height, packet_params.height,
&packet_params.name, &packet_params.name,
false, false,
)?; )?;
params params.tasks.push(wayvr::TickTask::NewDisplay(
.tasks packet_params,
.push(TickTask::NewDisplay(packet_params, Some(display_handle))); Some(display_handle),
));
send_packet( send_packet(
&mut self.conn, &mut self.conn,
@@ -235,6 +246,7 @@ impl Connection {
Ok(()) Ok(())
} }
#[cfg(feature = "wayvr")]
fn handle_wvr_display_remove( fn handle_wvr_display_remove(
&mut self, &mut self,
params: &mut TickParams, params: &mut TickParams,
@@ -242,8 +254,8 @@ impl Connection {
handle: packet_server::WvrDisplayHandle, handle: packet_server::WvrDisplayHandle,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let res = params let res = params
.state .wayland_state
.destroy_display(display::DisplayHandle::from_packet(handle)) .destroy_display(wayvr::display::DisplayHandle::from_packet(handle))
.map_err(|e| format!("{e:?}")); .map_err(|e| format!("{e:?}"));
send_packet( send_packet(
@@ -253,28 +265,31 @@ impl Connection {
Ok(()) Ok(())
} }
#[cfg(feature = "wayvr")]
fn handle_wvr_display_set_visible( fn handle_wvr_display_set_visible(
params: &mut TickParams, params: &mut TickParams,
handle: packet_server::WvrDisplayHandle, handle: packet_server::WvrDisplayHandle,
visible: bool, visible: bool,
) { ) {
params.state.signals.send(WayVRSignal::DisplayVisibility( params.signals.send(WayVRSignal::DisplayVisibility(
display::DisplayHandle::from_packet(handle), wayvr::display::DisplayHandle::from_packet(handle),
visible, visible,
)); ));
} }
#[cfg(feature = "wayvr")]
fn handle_wvr_display_set_window_layout( fn handle_wvr_display_set_window_layout(
params: &mut TickParams, params: &mut TickParams,
handle: packet_server::WvrDisplayHandle, handle: packet_server::WvrDisplayHandle,
layout: packet_server::WvrDisplayWindowLayout, layout: packet_server::WvrDisplayWindowLayout,
) { ) {
params.state.signals.send(WayVRSignal::DisplayWindowLayout( params.signals.send(WayVRSignal::DisplayWindowLayout(
display::DisplayHandle::from_packet(handle), wayvr::display::DisplayHandle::from_packet(handle),
layout, layout,
)); ));
} }
#[cfg(feature = "wayvr")]
fn handle_wvr_display_window_list( fn handle_wvr_display_window_list(
&mut self, &mut self,
params: &mut TickParams, params: &mut TickParams,
@@ -288,10 +303,13 @@ impl Connection {
) )
}; };
let Some(display) = params let Some(display) =
.state params
.displays .wayland_state
.get(&display::DisplayHandle::from_packet(display_handle.clone())) .displays
.get(&wayvr::display::DisplayHandle::from_packet(
display_handle.clone(),
))
else { else {
return send(None); return send(None);
}; };
@@ -302,14 +320,14 @@ impl Connection {
.iter() .iter()
.filter_map(|disp_win| { .filter_map(|disp_win| {
params params
.state .wayland_state
.wm .wm
.borrow_mut() .borrow_mut()
.windows .windows
.get(&disp_win.window_handle) .get(&disp_win.window_handle)
.map(|win| packet_server::WvrWindow { .map(|win| packet_server::WvrWindow {
handle: window::WindowHandle::as_packet(&disp_win.window_handle), handle: wayvr::window::WindowHandle::as_packet(&disp_win.window_handle),
process_handle: process::ProcessHandle::as_packet( process_handle: wayvr::process::ProcessHandle::as_packet(
&disp_win.process_handle, &disp_win.process_handle,
), ),
pos_x: win.pos_x, pos_x: win.pos_x,
@@ -324,17 +342,18 @@ impl Connection {
})) }))
} }
#[cfg(feature = "wayvr")]
fn handle_wvr_window_set_visible( fn handle_wvr_window_set_visible(
params: &mut TickParams, params: &mut TickParams,
handle: packet_server::WvrWindowHandle, handle: packet_server::WvrWindowHandle,
visible: bool, visible: bool,
) { ) {
let to_resize = if let Some(window) = params let to_resize = if let Some(window) = params
.state .wayland_state
.wm .wm
.borrow_mut() .borrow_mut()
.windows .windows
.get_mut(&window::WindowHandle::from_packet(handle)) .get_mut(&wayvr::window::WindowHandle::from_packet(handle))
{ {
window.visible = visible; window.visible = visible;
Some(window.display_handle) Some(window.display_handle)
@@ -343,13 +362,14 @@ impl Connection {
}; };
if let Some(to_resize) = to_resize if let Some(to_resize) = to_resize
&& let Some(display) = params.state.displays.get_mut(&to_resize) && let Some(display) = params.wayland_state.displays.get_mut(&to_resize)
{ {
display.reposition_windows(); display.reposition_windows();
display.trigger_rerender(); display.trigger_rerender();
} }
} }
#[cfg(feature = "wayvr")]
fn handle_wvr_process_launch( fn handle_wvr_process_launch(
&mut self, &mut self,
params: &mut TickParams, params: &mut TickParams,
@@ -359,8 +379,8 @@ impl Connection {
let args_vec = gen_args_vec(&packet_params.args); let args_vec = gen_args_vec(&packet_params.args);
let env_vec = gen_env_vec(&packet_params.env); let env_vec = gen_env_vec(&packet_params.env);
let res = params.state.spawn_process( let res = params.wayland_state.spawn_process(
super::display::DisplayHandle::from_packet(packet_params.target_display), wayvr::display::DisplayHandle::from_packet(packet_params.target_display),
&packet_params.exec, &packet_params.exec,
&args_vec, &args_vec,
&env_vec, &env_vec,
@@ -378,15 +398,16 @@ impl Connection {
Ok(()) Ok(())
} }
#[cfg(feature = "wayvr")]
fn handle_wvr_display_get( fn handle_wvr_display_get(
&mut self, &mut self,
params: &TickParams, params: &TickParams,
serial: ipc::Serial, serial: ipc::Serial,
display_handle: packet_server::WvrDisplayHandle, display_handle: packet_server::WvrDisplayHandle,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let native_handle = &display::DisplayHandle::from_packet(display_handle); let native_handle = &wayvr::display::DisplayHandle::from_packet(display_handle);
let disp = params let disp = params
.state .wayland_state
.displays .displays
.get(native_handle) .get(native_handle)
.map(|disp| disp.as_packet(*native_handle)); .map(|disp| disp.as_packet(*native_handle));
@@ -399,13 +420,14 @@ impl Connection {
Ok(()) Ok(())
} }
#[cfg(feature = "wayvr")]
fn handle_wvr_process_list( fn handle_wvr_process_list(
&mut self, &mut self,
params: &TickParams, params: &TickParams,
serial: ipc::Serial, serial: ipc::Serial,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let list: Vec<packet_server::WvrProcess> = params let list: Vec<packet_server::WvrProcess> = params
.state .wayland_state
.processes .processes
.vec .vec
.iter() .iter()
@@ -415,7 +437,10 @@ impl Connection {
return None; return None;
}; };
let process = &cell.obj; let process = &cell.obj;
Some(process.to_packet(process::ProcessHandle::new(idx as u32, cell.generation))) Some(process.to_packet(wayvr::process::ProcessHandle::new(
idx as u32,
cell.generation,
)))
}) })
.collect(); .collect();
@@ -431,12 +456,13 @@ impl Connection {
} }
// This request doesn't return anything to the client // This request doesn't return anything to the client
#[cfg(feature = "wayvr")]
fn handle_wvr_process_terminate( fn handle_wvr_process_terminate(
params: &mut TickParams, params: &mut TickParams,
process_handle: packet_server::WvrProcessHandle, process_handle: packet_server::WvrProcessHandle,
) { ) {
let native_handle = &process::ProcessHandle::from_packet(process_handle); let native_handle = &wayvr::process::ProcessHandle::from_packet(process_handle);
let process = params.state.processes.get_mut(native_handle); let process = params.wayland_state.processes.get_mut(native_handle);
let Some(process) = process else { let Some(process) = process else {
return; return;
@@ -445,15 +471,16 @@ impl Connection {
process.terminate(); process.terminate();
} }
#[cfg(feature = "wayvr")]
fn handle_wvr_process_get( fn handle_wvr_process_get(
&mut self, &mut self,
params: &TickParams, params: &TickParams,
serial: ipc::Serial, serial: ipc::Serial,
process_handle: packet_server::WvrProcessHandle, process_handle: packet_server::WvrProcessHandle,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let native_handle = &process::ProcessHandle::from_packet(process_handle); let native_handle = &wayvr::process::ProcessHandle::from_packet(process_handle);
let process = params let process = params
.state .wayland_state
.processes .processes
.get(native_handle) .get(native_handle)
.map(|process| process.to_packet(*native_handle)); .map(|process| process.to_packet(*native_handle));
@@ -466,17 +493,18 @@ impl Connection {
Ok(()) Ok(())
} }
#[cfg(feature = "wayvr")]
fn handle_wlx_haptics( fn handle_wlx_haptics(
params: &mut TickParams, params: &mut TickParams,
haptics_params: packet_client::WlxHapticsParams, haptics_params: packet_client::WlxHapticsParams,
) { ) {
params.state.signals.send(super::WayVRSignal::Haptics( params
crate::backend::input::Haptics { .signals
.send(WayVRSignal::Haptics(crate::backend::input::Haptics {
duration: haptics_params.duration, duration: haptics_params.duration,
frequency: haptics_params.frequency, frequency: haptics_params.frequency,
intensity: haptics_params.intensity, intensity: haptics_params.intensity,
}, }));
));
} }
fn handle_wlx_panel( fn handle_wlx_panel(
@@ -486,9 +514,8 @@ impl Connection {
use crate::backend::task::{ModifyPanelCommand, ModifyPanelTask}; use crate::backend::task::{ModifyPanelCommand, ModifyPanelTask};
params params
.state
.signals .signals
.send(super::WayVRSignal::CustomTask(ModifyPanelTask { .send(WayVRSignal::CustomTask(ModifyPanelTask {
overlay: custom_params.overlay, overlay: custom_params.overlay,
element: custom_params.element, element: custom_params.element,
command: match custom_params.command { command: match custom_params.command {
@@ -511,6 +538,9 @@ impl Connection {
})); }));
} }
// FIXME: we should probably respond an error to the client in case if wayland server feature is disabled
// fix this after we're done with the webkit-based wayvr-dashboard
#[allow(unused_variables)]
fn process_payload(&mut self, params: &mut TickParams, payload: Payload) -> anyhow::Result<()> { fn process_payload(&mut self, params: &mut TickParams, payload: Payload) -> anyhow::Result<()> {
let packet: PacketClient = ipc::data_decode(&payload)?; let packet: PacketClient = ipc::data_decode(&payload)?;
@@ -525,42 +555,55 @@ impl Connection {
self.handle_wlx_input_state(params, serial)?; self.handle_wlx_input_state(params, serial)?;
} }
PacketClient::WvrDisplayList(serial) => { PacketClient::WvrDisplayList(serial) => {
#[cfg(feature = "wayvr")]
self.handle_wvr_display_list(params, serial)?; self.handle_wvr_display_list(params, serial)?;
} }
PacketClient::WvrDisplayGet(serial, display_handle) => { PacketClient::WvrDisplayGet(serial, display_handle) => {
#[cfg(feature = "wayvr")]
self.handle_wvr_display_get(params, serial, display_handle)?; self.handle_wvr_display_get(params, serial, display_handle)?;
} }
PacketClient::WvrDisplayRemove(serial, display_handle) => { PacketClient::WvrDisplayRemove(serial, display_handle) => {
#[cfg(feature = "wayvr")]
self.handle_wvr_display_remove(params, serial, display_handle)?; self.handle_wvr_display_remove(params, serial, display_handle)?;
} }
PacketClient::WvrDisplaySetVisible(display_handle, visible) => { PacketClient::WvrDisplaySetVisible(display_handle, visible) => {
#[cfg(feature = "wayvr")]
Self::handle_wvr_display_set_visible(params, display_handle, visible); Self::handle_wvr_display_set_visible(params, display_handle, visible);
} }
PacketClient::WvrDisplaySetWindowLayout(display_handle, layout) => { PacketClient::WvrDisplaySetWindowLayout(display_handle, layout) => {
#[cfg(feature = "wayvr")]
Self::handle_wvr_display_set_window_layout(params, display_handle, layout); Self::handle_wvr_display_set_window_layout(params, display_handle, layout);
} }
PacketClient::WvrDisplayWindowList(serial, display_handle) => { PacketClient::WvrDisplayWindowList(serial, display_handle) => {
#[cfg(feature = "wayvr")]
self.handle_wvr_display_window_list(params, serial, display_handle)?; self.handle_wvr_display_window_list(params, serial, display_handle)?;
} }
PacketClient::WvrWindowSetVisible(window_handle, visible) => { PacketClient::WvrWindowSetVisible(window_handle, visible) => {
#[cfg(feature = "wayvr")]
Self::handle_wvr_window_set_visible(params, window_handle, visible); Self::handle_wvr_window_set_visible(params, window_handle, visible);
} }
PacketClient::WvrProcessGet(serial, process_handle) => { PacketClient::WvrProcessGet(serial, process_handle) => {
#[cfg(feature = "wayvr")]
self.handle_wvr_process_get(params, serial, process_handle)?; self.handle_wvr_process_get(params, serial, process_handle)?;
} }
PacketClient::WvrProcessList(serial) => { PacketClient::WvrProcessList(serial) => {
#[cfg(feature = "wayvr")]
self.handle_wvr_process_list(params, serial)?; self.handle_wvr_process_list(params, serial)?;
} }
PacketClient::WvrProcessLaunch(serial, packet_params) => { PacketClient::WvrProcessLaunch(serial, packet_params) => {
#[cfg(feature = "wayvr")]
self.handle_wvr_process_launch(params, serial, packet_params)?; self.handle_wvr_process_launch(params, serial, packet_params)?;
} }
PacketClient::WvrDisplayCreate(serial, packet_params) => { PacketClient::WvrDisplayCreate(serial, packet_params) => {
#[cfg(feature = "wayvr")]
self.handle_wvr_display_create(params, serial, packet_params)?; self.handle_wvr_display_create(params, serial, packet_params)?;
} }
PacketClient::WvrProcessTerminate(process_handle) => { PacketClient::WvrProcessTerminate(process_handle) => {
#[cfg(feature = "wayvr")]
Self::handle_wvr_process_terminate(params, process_handle); Self::handle_wvr_process_terminate(params, process_handle);
} }
PacketClient::WlxHaptics(haptics_params) => { PacketClient::WlxHaptics(haptics_params) => {
#[cfg(feature = "wayvr")]
Self::handle_wlx_haptics(params, haptics_params); Self::handle_wlx_haptics(params, haptics_params);
} }
PacketClient::WlxModifyPanel(custom_params) => { PacketClient::WlxModifyPanel(custom_params) => {

View File

@@ -0,0 +1,4 @@
pub mod event_queue;
pub mod events;
pub mod ipc_server;
pub mod signal;

View File

@@ -0,0 +1,19 @@
#[cfg(feature = "wayvr")]
use crate::backend::wayvr;
#[derive(Clone)]
pub enum WayVRSignal {
#[cfg(feature = "wayvr")]
DisplayVisibility(wayvr::display::DisplayHandle, bool),
#[cfg(feature = "wayvr")]
DisplayWindowLayout(
wayvr::display::DisplayHandle,
wayvr_ipc::packet_server::WvrDisplayWindowLayout,
),
#[cfg(feature = "wayvr")]
BroadcastStateChanged(wayvr_ipc::packet_server::WvrStateChanged),
#[cfg(feature = "wayvr")]
Haptics(crate::backend::input::Haptics),
DropOverlay(crate::windowing::OverlayID),
CustomTask(crate::backend::task::ModifyPanelTask),
}

View File

@@ -22,6 +22,7 @@ mod config;
mod config_io; mod config_io;
mod graphics; mod graphics;
mod gui; mod gui;
mod ipc;
mod overlays; mod overlays;
mod shaders; mod shaders;
mod state; mod state;

View File

@@ -22,13 +22,11 @@ use crate::{
backend::{ backend::{
input::{self, HoverResult}, input::{self, HoverResult},
task::{OverlayTask, TaskType}, task::{OverlayTask, TaskType},
wayvr::{ wayvr::{self, WayVR, WayVRAction, WayVRDisplayClickAction, display},
self, WayVR, WayVRAction, WayVRDisplayClickAction, display,
server_ipc::{gen_args_vec, gen_env_vec},
},
}, },
config_wayvr, config_wayvr,
graphics::{Vert2Uv, dmabuf::WGfxDmabuf}, graphics::{Vert2Uv, dmabuf::WGfxDmabuf},
ipc::{event_queue::SyncEventQueue, ipc_server, signal::WayVRSignal},
state::{self, AppState}, state::{self, AppState},
subsystem::{hid::WheelDelta, input::KeyboardFocus}, subsystem::{hid::WheelDelta, input::KeyboardFocus},
windowing::{ windowing::{
@@ -63,31 +61,34 @@ impl WayVRContext {
} }
} }
struct OverlayToCreate { pub struct OverlayToCreate {
pub conf_display: config_wayvr::WayVRDisplay, pub conf_display: config_wayvr::WayVRDisplay,
pub disp_handle: display::DisplayHandle, pub disp_handle: display::DisplayHandle,
} }
pub struct WayVRData { pub struct WayVRData {
display_handle_map: HashMap<display::DisplayHandle, OverlayID>, pub display_handle_map: HashMap<display::DisplayHandle, OverlayID>,
overlays_to_create: Vec<OverlayToCreate>, pub overlays_to_create: Vec<OverlayToCreate>,
dashboard_executed: bool, pub dashboard_executed: bool,
pub data: WayVR, pub data: WayVR,
pending_haptics: Option<input::Haptics>, pub pending_haptics: Option<input::Haptics>,
} }
impl WayVRData { impl WayVRData {
pub fn new(config: wayvr::Config) -> anyhow::Result<Self> { pub fn new(
config: wayvr::Config,
signals: SyncEventQueue<WayVRSignal>,
) -> anyhow::Result<Self> {
Ok(Self { Ok(Self {
display_handle_map: HashMap::default(), display_handle_map: HashMap::default(),
data: WayVR::new(config)?, data: WayVR::new(config, signals)?,
overlays_to_create: Vec::new(), overlays_to_create: Vec::new(),
dashboard_executed: false, dashboard_executed: false,
pending_haptics: None, pending_haptics: None,
}) })
} }
fn get_unique_display_name(&self, mut candidate: String) -> String { pub fn get_unique_display_name(&self, mut candidate: String) -> String {
let mut num = 0; let mut num = 0;
while !self while !self
@@ -179,7 +180,7 @@ impl WayVRBackend {
} }
} }
fn get_or_create_display_by_name( pub fn get_or_create_display_by_name(
app: &mut AppState, app: &mut AppState,
wayvr: &mut WayVRData, wayvr: &mut WayVRData,
disp_name: &str, disp_name: &str,
@@ -290,12 +291,12 @@ where
let args_vec = &conf_dash let args_vec = &conf_dash
.args .args
.as_ref() .as_ref()
.map_or_else(Vec::new, |args| gen_args_vec(args.as_str())); .map_or_else(Vec::new, |args| ipc_server::gen_args_vec(args.as_str()));
let env_vec = &conf_dash let env_vec = &conf_dash
.env .env
.as_ref() .as_ref()
.map_or_else(Vec::new, |env| gen_env_vec(env)); .map_or_else(Vec::new, |env| ipc_server::gen_env_vec(env));
let mut userdata = HashMap::new(); let mut userdata = HashMap::new();
userdata.insert(String::from("type"), String::from("dashboard")); userdata.insert(String::from("type"), String::from("dashboard"));
@@ -322,9 +323,7 @@ where
let cur_visibility = !display.visible; let cur_visibility = !display.visible;
wayvr app.ipc_server
.data
.ipc_server
.broadcast(PacketServer::WvrStateChanged(if cur_visibility { .broadcast(PacketServer::WvrStateChanged(if cur_visibility {
WvrStateChanged::DashboardShown WvrStateChanged::DashboardShown
} else { } else {
@@ -379,7 +378,7 @@ fn create_overlay(
Ok(overlay) Ok(overlay)
} }
fn create_queued_displays<O>( pub fn create_queued_displays<O>(
app: &mut AppState, app: &mut AppState,
data: &mut WayVRData, data: &mut WayVRData,
overlays: &mut OverlayWindowManager<O>, overlays: &mut OverlayWindowManager<O>,
@@ -405,152 +404,6 @@ where
Ok(()) Ok(())
} }
#[allow(clippy::too_many_lines)]
pub fn tick_events<O>(
app: &mut AppState,
overlays: &mut OverlayWindowManager<O>,
) -> anyhow::Result<()>
where
O: Default,
{
let Some(r_wayvr) = app.wayvr.clone() else {
return Ok(());
};
let mut wayvr = r_wayvr.borrow_mut();
while let Some(signal) = wayvr.data.state.signals.read() {
match signal {
wayvr::WayVRSignal::DisplayVisibility(display_handle, visible) => {
if let Some(overlay_id) = wayvr.display_handle_map.get(&display_handle) {
let overlay_id = *overlay_id;
wayvr
.data
.state
.set_display_visible(display_handle, visible);
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Modify(
OverlaySelector::Id(overlay_id),
Box::new(move |app, o| {
if visible == o.is_active() {
return;
}
if visible {
o.activate(app);
} else {
o.deactivate();
}
}),
)));
}
}
wayvr::WayVRSignal::DisplayWindowLayout(display_handle, layout) => {
wayvr.data.state.set_display_layout(display_handle, layout);
}
wayvr::WayVRSignal::BroadcastStateChanged(packet) => {
wayvr
.data
.ipc_server
.broadcast(packet_server::PacketServer::WvrStateChanged(packet));
}
wayvr::WayVRSignal::DropOverlay(overlay_id) => {
app.tasks
.enqueue(TaskType::Overlay(OverlayTask::Drop(OverlaySelector::Id(
overlay_id,
))));
}
wayvr::WayVRSignal::Haptics(haptics) => {
wayvr.pending_haptics = Some(haptics);
}
wayvr::WayVRSignal::CustomTask(custom_task) => {
app.tasks
.enqueue(TaskType::Overlay(OverlayTask::ModifyPanel(custom_task)));
}
}
}
let res = wayvr.data.tick_events(app)?;
drop(wayvr);
for result in res {
match result {
wayvr::TickTask::NewExternalProcess(request) => {
let config = &app.session.wayvr_config;
let disp_name = request.env.display_name.map_or_else(
|| {
config
.get_default_display()
.map(|(display_name, _)| display_name)
},
|display_name| {
config
.get_display(display_name.as_str())
.map(|_| display_name)
},
);
if let Some(disp_name) = disp_name {
let mut wayvr = r_wayvr.borrow_mut();
log::info!("Registering external process with PID {}", request.pid);
let disp_handle = get_or_create_display_by_name(app, &mut wayvr, &disp_name)?;
wayvr
.data
.state
.add_external_process(disp_handle, request.pid);
wayvr
.data
.state
.manager
.add_client(wayvr::client::WayVRClient {
client: request.client,
display_handle: disp_handle,
pid: request.pid,
});
}
}
wayvr::TickTask::NewDisplay(cpar, disp_handle) => {
log::info!("Creating new display with name \"{}\"", cpar.name);
let mut wayvr = r_wayvr.borrow_mut();
let unique_name = wayvr.get_unique_display_name(cpar.name);
let disp_handle = match disp_handle {
Some(d) => d,
None => wayvr.data.state.create_display(
cpar.width,
cpar.height,
&unique_name,
false,
)?,
};
wayvr.overlays_to_create.push(OverlayToCreate {
disp_handle,
conf_display: config_wayvr::WayVRDisplay {
attach_to: Some(config_wayvr::AttachTo::from_packet(&cpar.attach_to)),
width: cpar.width,
height: cpar.height,
pos: None,
primary: None,
rotation: None,
scale: cpar.scale,
},
});
}
}
}
let mut wayvr = r_wayvr.borrow_mut();
create_queued_displays(app, &mut wayvr, overlays)?;
Ok(())
}
impl WayVRBackend { impl WayVRBackend {
fn ensure_software_data( fn ensure_software_data(
&mut self, &mut self,
@@ -805,7 +658,7 @@ pub fn create_wayvr_display_overlay(
display_scale: f32, display_scale: f32,
name: &str, name: &str,
) -> anyhow::Result<OverlayWindowConfig> { ) -> anyhow::Result<OverlayWindowConfig> {
let wayvr = app.get_wayvr()?; let wayvr = app.wayvr.clone();
let backend = Box::new(WayVRBackend::new( let backend = Box::new(WayVRBackend::new(
app, app,
@@ -866,7 +719,7 @@ fn action_app_click<O>(
where where
O: Default, O: Default,
{ {
let wayvr = app.get_wayvr()?; let wayvr = app.wayvr.clone();
let catalog = app let catalog = app
.session .session
@@ -887,12 +740,12 @@ where
let args_vec = &app_entry let args_vec = &app_entry
.args .args
.as_ref() .as_ref()
.map_or_else(Vec::new, |args| gen_args_vec(args.as_str())); .map_or_else(Vec::new, |args| ipc_server::gen_args_vec(args.as_str()));
let env_vec = &app_entry let env_vec = &app_entry
.env .env
.as_ref() .as_ref()
.map_or_else(Vec::new, |env| gen_env_vec(env)); .map_or_else(Vec::new, |env| ipc_server::gen_env_vec(env));
// Terminate existing process if required // Terminate existing process if required
if let Some(process_handle) = if let Some(process_handle) =
@@ -930,7 +783,7 @@ pub fn action_display_click<O>(
where where
O: Default, O: Default,
{ {
let wayvr = app.get_wayvr()?; let wayvr = app.wayvr.clone();
let mut wayvr = wayvr.borrow_mut(); let mut wayvr = wayvr.borrow_mut();
let Some(handle) = WayVR::get_display_by_name(&wayvr.data.state.displays, display_name) else { let Some(handle) = WayVR::get_display_by_name(&wayvr.data.state.displays, display_name) else {
@@ -990,14 +843,7 @@ pub fn wayvr_action<O>(
} }
} }
WayVRAction::ToggleDashboard => { WayVRAction::ToggleDashboard => {
let wayvr = match app.get_wayvr() { let wayvr = app.wayvr.clone();
Ok(wayvr) => wayvr,
Err(e) => {
log::error!("WayVR Error: {e:?}");
return;
}
};
let mut wayvr = wayvr.borrow_mut(); let mut wayvr = wayvr.borrow_mut();
if let Err(e) = toggle_dashboard::<O>(app, overlays, &mut wayvr) { if let Err(e) = toggle_dashboard::<O>(app, overlays, &mut wayvr) {

View File

@@ -12,11 +12,6 @@ version: 1
# "software": Read pixel data to memory via glReadPixels() every time a content has been updated. Minor performance impact on large resolutions # "software": Read pixel data to memory via glReadPixels() every time a content has been updated. Minor performance impact on large resolutions
blit_method: "dmabuf" blit_method: "dmabuf"
# Set to true if you want to make Wyland server instantly available.
# By default, WayVR starts only when it's needed.
# (this option is primarily used for remote starting external processes and development purposes)
run_compositor_at_start: false
# Automatically close overlays with zero window count? # Automatically close overlays with zero window count?
auto_hide: true auto_hide: true

View File

@@ -27,6 +27,7 @@ use crate::{
config_io::{self, get_config_file_path}, config_io::{self, get_config_file_path},
graphics::WGfxExtras, graphics::WGfxExtras,
gui, gui,
ipc::{event_queue::SyncEventQueue, ipc_server, signal::WayVRSignal},
subsystem::{audio::AudioOutput, dbus::DbusConnector, input::HidWrapper}, subsystem::{audio::AudioOutput, dbus::DbusConnector, input::HidWrapper},
}; };
@@ -53,11 +54,16 @@ pub struct AppState {
pub xr_backend: XrBackend, pub xr_backend: XrBackend,
pub ipc_server: ipc_server::WayVRServer,
pub wayvr_signals: SyncEventQueue<WayVRSignal>,
#[cfg(feature = "osc")] #[cfg(feature = "osc")]
pub osc_sender: Option<OscSender>, pub osc_sender: Option<OscSender>,
// wayland server
// TODO: rename to wayland_server?
#[cfg(feature = "wayvr")] #[cfg(feature = "wayvr")]
pub wayvr: Option<Rc<RefCell<WayVRData>>>, // Dynamically created if requested pub wayvr: Rc<RefCell<WayVRData>>,
} }
#[allow(unused_mut)] #[allow(unused_mut)]
@@ -71,18 +77,18 @@ impl AppState {
let mut tasks = TaskContainer::new(); let mut tasks = TaskContainer::new();
let session = AppSession::load(); let session = AppSession::load();
let wayvr_signals = SyncEventQueue::new();
#[cfg(feature = "wayvr")] #[cfg(feature = "wayvr")]
let wayvr = session let wayvr =
.wayvr_config session
.post_load(&session.config, &mut tasks)?; .wayvr_config
.post_load(&session.config, &mut tasks, wayvr_signals.clone())?;
let mut hid_provider = HidWrapper::new(); let mut hid_provider = HidWrapper::new();
#[cfg(feature = "wayvr")] #[cfg(feature = "wayvr")]
if let Some(wayvr) = wayvr.as_ref() { hid_provider.set_wayvr(wayvr.clone());
hid_provider.set_wayvr(wayvr.clone());
}
#[cfg(feature = "osc")] #[cfg(feature = "osc")]
let osc_sender = crate::subsystem::osc::OscSender::new(session.config.osc_out_port).ok(); let osc_sender = crate::subsystem::osc::OscSender::new(session.config.osc_out_port).ok();
@@ -114,6 +120,8 @@ impl AppState {
let dbus = DbusConnector::default(); let dbus = DbusConnector::default();
let ipc_server = ipc_server::WayVRServer::new()?;
Ok(Self { Ok(Self {
session, session,
tasks, tasks,
@@ -135,6 +143,8 @@ impl AppState {
)?, )?,
dbus, dbus,
xr_backend, xr_backend,
ipc_server,
wayvr_signals,
#[cfg(feature = "osc")] #[cfg(feature = "osc")]
osc_sender, osc_sender,
@@ -144,21 +154,6 @@ impl AppState {
}) })
} }
#[cfg(feature = "wayvr")]
#[allow(dead_code)]
pub fn get_wayvr(&mut self) -> anyhow::Result<Rc<RefCell<WayVRData>>> {
if let Some(wvr) = &self.wayvr {
Ok(wvr.clone())
} else {
let wayvr = Rc::new(RefCell::new(WayVRData::new(
WayVRConfig::get_wayvr_config(&self.session.config, &self.session.wayvr_config)?,
)?));
self.hid_provider.set_wayvr(wayvr.clone());
self.wayvr = Some(wayvr.clone());
Ok(wayvr)
}
}
pub fn try_load_bytes(path: &str, fallback_data: &'static [u8]) -> &'static [u8] { pub fn try_load_bytes(path: &str, fallback_data: &'static [u8]) -> &'static [u8] {
if path.is_empty() { if path.is_empty() {
return fallback_data; return fallback_data;
@@ -187,7 +182,7 @@ pub struct AppSession {
pub config: GeneralConfig, pub config: GeneralConfig,
#[cfg(feature = "wayvr")] #[cfg(feature = "wayvr")]
pub wayvr_config: WayVRConfig, pub wayvr_config: WayVRConfig, // TODO: rename to "wayland_server_config"
pub toast_topics: IdMap<ToastTopic, ToastDisplayMethod>, pub toast_topics: IdMap<ToastTopic, ToastDisplayMethod>,
} }