diff --git a/Cargo.lock b/Cargo.lock index 5807430..1662153 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4582,7 +4582,7 @@ dependencies = [ [[package]] name = "wayvr_ipc" version = "0.1.0" -source = "git+https://github.com/olekolek1000/wayvr-ipc.git?rev=fe2e8be04c7b86adcf972be7ebe46961bd881f35#fe2e8be04c7b86adcf972be7ebe46961bd881f35" +source = "git+https://github.com/olekolek1000/wayvr-ipc.git?rev=3c411d09ba1bba2609288e29739c0f1ec736b012#3c411d09ba1bba2609288e29739c0f1ec736b012" dependencies = [ "anyhow", "bytes", diff --git a/Cargo.toml b/Cargo.toml index ef5178e..f1d8e91 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -86,7 +86,7 @@ wayland-client = { version = "0.31.6", optional = true } wayland-egl = { version = "0.32.4", optional = true } interprocess = { version = "2.2.2", optional = true } bytes = { version = "1.9.0", optional = true } -wayvr_ipc = { git = "https://github.com/olekolek1000/wayvr-ipc.git", rev = "fe2e8be04c7b86adcf972be7ebe46961bd881f35", default-features = false, optional = true } +wayvr_ipc = { git = "https://github.com/olekolek1000/wayvr-ipc.git", rev = "3c411d09ba1bba2609288e29739c0f1ec736b012", default-features = false, optional = true } ################################ [build-dependencies] diff --git a/src/backend/openvr/mod.rs b/src/backend/openvr/mod.rs index 859ed38..e74cb96 100644 --- a/src/backend/openvr/mod.rs +++ b/src/backend/openvr/mod.rs @@ -334,7 +334,11 @@ pub fn openvr_run(running: Arc, show_by_default: bool) -> Result<(), }; #[cfg(feature = "wayvr")] - crate::overlays::wayvr::tick_events::(&mut state, &mut overlays)?; + if let Err(e) = + crate::overlays::wayvr::tick_events::(&mut state, &mut overlays) + { + log::error!("WayVR tick_events failed: {:?}", e); + } log::trace!("Rendering frame"); diff --git a/src/backend/openxr/mod.rs b/src/backend/openxr/mod.rs index cb06a7c..0bbf48a 100644 --- a/src/backend/openxr/mod.rs +++ b/src/backend/openxr/mod.rs @@ -382,7 +382,11 @@ pub fn openxr_run(running: Arc, show_by_default: bool) -> Result<(), } #[cfg(feature = "wayvr")] - crate::overlays::wayvr::tick_events::(&mut app_state, &mut overlays)?; + if let Err(e) = + crate::overlays::wayvr::tick_events::(&mut app_state, &mut overlays) + { + log::error!("WayVR tick_events failed: {:?}", e); + } for o in overlays.iter_mut() { if !o.state.want_visible { diff --git a/src/backend/wayvr/display.rs b/src/backend/wayvr/display.rs index f1b5624..de9f439 100644 --- a/src/backend/wayvr/display.rs +++ b/src/backend/wayvr/display.rs @@ -35,7 +35,7 @@ fn generate_auth_key() -> String { pub struct DisplayWindow { pub window_handle: window::WindowHandle, pub toplevel: ToplevelSurface, - process_handle: process::ProcessHandle, + pub process_handle: process::ProcessHandle, } pub struct SpawnProcessResult { @@ -57,6 +57,7 @@ pub struct Display { pub height: u16, pub name: String, pub visible: bool, + pub layout: packet_server::WvrDisplayWindowLayout, pub overlay_id: Option, pub wants_redraw: bool, pub primary: bool, @@ -84,29 +85,31 @@ impl Drop for Display { } } +pub struct DisplayInitParams<'a> { + pub wm: Rc>, + pub renderer: &'a mut GlesRenderer, + pub egl_data: Rc, + pub wayland_env: super::WaylandEnv, + pub width: u16, + pub height: u16, + pub name: &'a str, + pub primary: bool, +} + impl Display { - pub fn new( - wm: Rc>, - renderer: &mut GlesRenderer, - egl_data: Rc, - wayland_env: super::WaylandEnv, - width: u16, - height: u16, - name: &str, - primary: bool, - ) -> anyhow::Result { - if width > MAX_DISPLAY_SIZE { + pub fn new(params: DisplayInitParams) -> anyhow::Result { + if params.width > MAX_DISPLAY_SIZE { anyhow::bail!( "display width ({}) is larger than {}", - width, + params.width, MAX_DISPLAY_SIZE ); } - if height > MAX_DISPLAY_SIZE { + if params.height > MAX_DISPLAY_SIZE { anyhow::bail!( "display height ({}) is larger than {}", - height, + params.height, MAX_DISPLAY_SIZE ); } @@ -114,42 +117,44 @@ impl Display { let tex_format = ffi::RGBA; let internal_format = ffi::RGBA8; - let tex_id = renderer.with_context(|gl| { + let tex_id = params.renderer.with_context(|gl| { smithay_wrapper::create_framebuffer_texture( gl, - width as u32, - height as u32, + params.width as u32, + params.height as u32, tex_format, internal_format, ) })?; - let egl_image = egl_data.create_egl_image(tex_id)?; - let dmabuf_data = egl_data.create_dmabuf_data(&egl_image)?; + let egl_image = params.egl_data.create_egl_image(tex_id)?; + let dmabuf_data = params.egl_data.create_dmabuf_data(&egl_image)?; let opaque = false; - let size = (width as i32, height as i32).into(); - let gles_texture = - unsafe { GlesTexture::from_raw(renderer, Some(tex_format), opaque, tex_id, size) }; + let size = (params.width as i32, params.height as i32).into(); + let gles_texture = unsafe { + GlesTexture::from_raw(params.renderer, Some(tex_format), opaque, tex_id, size) + }; Ok(Self { - wm, - width, - height, - name: String::from(name), + egl_data: params.egl_data, + width: params.width, + height: params.height, + name: String::from(params.name), + primary: params.primary, + wayland_env: params.wayland_env, + wm: params.wm, displayed_windows: Vec::new(), - wants_redraw: true, - egl_data, dmabuf_data, egl_image, gles_texture, - wayland_env, - visible: true, - primary, - overlay_id: None, - tasks: SyncEventQueue::new(), last_pressed_time_ms: 0, no_windows_since: None, + overlay_id: None, + tasks: SyncEventQueue::new(), + visible: true, + wants_redraw: true, + layout: packet_server::WvrDisplayWindowLayout::Tiling, }) } @@ -178,19 +183,62 @@ impl Display { self.reposition_windows(); } - fn reposition_windows(&mut self) { + pub fn reposition_windows(&mut self) { let window_count = self.displayed_windows.len(); - for (i, win) in self.displayed_windows.iter_mut().enumerate() { - if let Some(window) = self.wm.borrow_mut().windows.get_mut(&win.window_handle) { - let d_cur = i as f32 / window_count as f32; - let d_next = (i + 1) as f32 / window_count as f32; - - let left = (d_cur * self.width as f32) as i32; - let right = (d_next * self.width as f32) as i32; + match &self.layout { + packet_server::WvrDisplayWindowLayout::Tiling => { + let mut i = 0; + for win in self.displayed_windows.iter_mut() { + if let Some(window) = self.wm.borrow_mut().windows.get_mut(&win.window_handle) { + if !window.visible { + continue; + } + let d_cur = i as f32 / window_count as f32; + let d_next = (i + 1) as f32 / window_count as f32; + + let left = (d_cur * self.width as f32) as i32; + let right = (d_next * self.width as f32) as i32; + + window.set_pos(left, 0); + window.set_size((right - left) as u32, self.height as u32); + i += 1; + } + } + } + packet_server::WvrDisplayWindowLayout::Stacking(opts) => { + let do_margins = |margins: &packet_server::Margins, window: &mut window::Window| { + let top = margins.top as i32; + let bottom = self.height as i32 - margins.bottom as i32; + let left = margins.left as i32; + let right = self.width as i32 - margins.right as i32; + let width = right - left; + let height = bottom - top; + if width < 0 || height < 0 { + return; // wrong parameters, do nothing! + } - window.set_pos(left, 0); - window.set_size((right - left) as u32, self.height as u32); + window.set_pos(left, top); + window.set_size(width as u32, height as u32); + }; + + let mut i = 0; + for win in self.displayed_windows.iter_mut() { + if let Some(window) = self.wm.borrow_mut().windows.get_mut(&win.window_handle) { + if !window.visible { + continue; + } + do_margins( + if i == 0 { + &opts.margins_first + } else { + &opts.margins_rest + }, + window, + ); + i += 1; + } + } } } } @@ -217,6 +265,7 @@ impl Display { while let Some(task) = self.tasks.read() { match task { DisplayTask::ProcessCleanup(process_handle) => { + let count = self.displayed_windows.len(); self.displayed_windows .retain(|win| win.process_handle != process_handle); log::info!( @@ -226,6 +275,12 @@ impl Display { ); self.no_windows_since = Some(get_millis()); + if count != self.displayed_windows.len() { + signals.send(WayVRSignal::BroadcastStateChanged( + packet_server::WvrStateChanged::WindowRemoved, + )); + } + self.reposition_windows(); } } @@ -245,6 +300,9 @@ impl Display { .flat_map(|display_window| { let wm = self.wm.borrow_mut(); if let Some(window) = wm.windows.get(&display_window.window_handle) { + if !window.visible { + return vec![]; + } render_elements_from_surface_tree( renderer, display_window.toplevel.wl_surface(), @@ -284,8 +342,12 @@ impl Display { fn get_hovered_window(&self, cursor_x: u32, cursor_y: u32) -> Option { let wm = self.wm.borrow(); - for cell in self.displayed_windows.iter() { + for cell in self.displayed_windows.iter().rev() { if let Some(window) = wm.windows.get(&cell.window_handle) { + if !window.visible { + continue; + } + if (cursor_x as i32) >= window.pos_x && (cursor_x as i32) < window.pos_x + window.size_x as i32 && (cursor_y as i32) >= window.pos_y @@ -298,15 +360,30 @@ impl Display { None } + pub fn trigger_rerender(&mut self) { + self.wants_redraw = true; + } + pub fn set_visible(&mut self, visible: bool) { log::info!("Display \"{}\" visible: {}", self.name.as_str(), visible); - if self.visible != visible { - self.visible = visible; - if visible { - self.wants_redraw = true; - self.no_windows_since = None; - } + if self.visible == visible { + return; } + self.visible = visible; + if visible { + self.no_windows_since = None; + self.trigger_rerender(); + } + } + + pub fn set_layout(&mut self, layout: packet_server::WvrDisplayWindowLayout) { + log::info!("Display \"{}\" layout: {:?}", self.name.as_str(), layout); + if self.layout == layout { + return; + } + self.layout = layout; + self.trigger_rerender(); + self.reposition_windows(); } pub fn send_mouse_move( diff --git a/src/backend/wayvr/mod.rs b/src/backend/wayvr/mod.rs index eb5a4da..12fb5bf 100644 --- a/src/backend/wayvr/mod.rs +++ b/src/backend/wayvr/mod.rs @@ -11,7 +11,7 @@ mod smithay_wrapper; mod time; mod window; use comp::Application; -use display::DisplayVec; +use display::{DisplayInitParams, DisplayVec}; use event_queue::SyncEventQueue; use process::ProcessVec; use server_ipc::WayVRServer; @@ -32,9 +32,13 @@ use smithay::{ shm::ShmState, }, }; -use std::{cell::RefCell, collections::HashSet, rc::Rc}; +use std::{ + cell::RefCell, + collections::{HashMap, HashSet}, + rc::Rc, +}; use time::get_millis; -use wayvr_ipc::packet_client; +use wayvr_ipc::{packet_client, packet_server}; const STR_INVALID_HANDLE_DISP: &str = "Invalid display handle"; const STR_INVALID_HANDLE_PROCESS: &str = "Invalid process handle"; @@ -76,6 +80,11 @@ pub enum WayVRTask { #[derive(Clone)] pub enum WayVRSignal { DisplayVisibility(display::DisplayHandle, bool), + DisplayWindowLayout( + display::DisplayHandle, + packet_server::WvrDisplayWindowLayout, + ), + BroadcastStateChanged(packet_server::WvrStateChanged), } pub struct Config { @@ -102,7 +111,7 @@ pub struct WayVRState { pub struct WayVR { pub state: WayVRState, - ipc_server: WayVRServer, + pub ipc_server: WayVRServer, } pub enum MouseIndex { @@ -302,13 +311,13 @@ impl WayVR { } }); - for (p_handle, disp_handle) in to_remove { - self.state.processes.remove(&p_handle); + for (p_handle, disp_handle) in &to_remove { + self.state.processes.remove(p_handle); - if let Some(display) = self.state.displays.get_mut(&disp_handle) { + if let Some(display) = self.state.displays.get_mut(disp_handle) { display .tasks - .send(display::DisplayTask::ProcessCleanup(p_handle)); + .send(display::DisplayTask::ProcessCleanup(*p_handle)); display.wants_redraw = true; } } @@ -317,6 +326,12 @@ impl WayVR { display.tick(&self.state.config, &handle, &mut self.state.signals); }); + if !to_remove.is_empty() { + self.state.signals.send(WayVRSignal::BroadcastStateChanged( + packet_server::WvrStateChanged::ProcessRemoved, + )); + } + while let Some(task) = self.state.tasks.read() { match task { WayVRTask::NewExternalProcess(req) => { @@ -329,15 +344,22 @@ impl WayVR { // Attach newly created toplevel surfaces to displays for client in &self.state.manager.clients { if client.client.id() == client_id { - let window_handle = self.state.wm.borrow_mut().create_window(&toplevel); - if let Some(process_handle) = process::find_by_pid(&self.state.processes, client.pid) { + let window_handle = self + .state + .wm + .borrow_mut() + .create_window(client.display_handle, &toplevel); + if let Some(display) = self.state.displays.get_mut(&client.display_handle) { display.add_window(window_handle, process_handle, &toplevel); + self.state.signals.send(WayVRSignal::BroadcastStateChanged( + packet_server::WvrStateChanged::WindowCreated, + )); } else { // This shouldn't happen, scream if it does log::error!("Could not attach window handle into display"); @@ -456,6 +478,16 @@ impl WayVRState { } } + pub fn set_display_layout( + &mut self, + display: display::DisplayHandle, + layout: packet_server::WvrDisplayWindowLayout, + ) { + if let Some(display) = self.displays.get_mut(&display) { + display.set_layout(layout); + } + } + pub fn get_dmabuf_data(&self, display: display::DisplayHandle) -> Option { self.displays .get(&display) @@ -469,17 +501,24 @@ impl WayVRState { name: &str, primary: bool, ) -> anyhow::Result { - let display = display::Display::new( - self.wm.clone(), - &mut self.manager.state.gles_renderer, - self.egl_data.clone(), - self.manager.wayland_env.clone(), + let display = display::Display::new(DisplayInitParams { + wm: self.wm.clone(), + egl_data: self.egl_data.clone(), + renderer: &mut self.manager.state.gles_renderer, + wayland_env: self.manager.wayland_env.clone(), width, height, name, primary, - )?; - Ok(self.displays.add(display)) + })?; + + let handle = self.displays.add(display); + + self.signals.send(WayVRSignal::BroadcastStateChanged( + packet_server::WvrStateChanged::DisplayCreated, + )); + + Ok(handle) } pub fn destroy_display(&mut self, handle: display::DisplayHandle) -> anyhow::Result<()> { @@ -519,6 +558,10 @@ impl WayVRState { self.displays.remove(&handle); + self.signals.send(WayVRSignal::BroadcastStateChanged( + packet_server::WvrStateChanged::DisplayRemoved, + )); + Ok(()) } @@ -584,6 +627,7 @@ impl WayVRState { exec_path: &str, args: &[&str], env: &[(&str, &str)], + userdata: HashMap, ) -> anyhow::Result { let display = self .displays @@ -591,18 +635,26 @@ impl WayVRState { .ok_or(anyhow::anyhow!(STR_INVALID_HANDLE_DISP))?; let res = display.spawn_process(exec_path, args, env)?; - Ok(self + + let handle = self .processes .add(process::Process::Managed(process::WayVRProcess { auth_key: res.auth_key, child: res.child, display_handle, exec_path: String::from(exec_path), + userdata, args: args.iter().map(|x| String::from(*x)).collect(), env: env .iter() .map(|(a, b)| (String::from(*a), String::from(*b))) .collect(), - }))) + })); + + self.signals.send(WayVRSignal::BroadcastStateChanged( + packet_server::WvrStateChanged::ProcessCreated, + )); + + Ok(handle) } } diff --git a/src/backend/wayvr/process.rs b/src/backend/wayvr/process.rs index 62114df..ebd7135 100644 --- a/src/backend/wayvr/process.rs +++ b/src/backend/wayvr/process.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use wayvr_ipc::packet_server; use crate::gen_id; @@ -13,6 +15,8 @@ pub struct WayVRProcess { pub exec_path: String, pub args: Vec, pub env: Vec<(String, String)>, + + pub userdata: HashMap, } #[derive(Debug)] @@ -60,11 +64,13 @@ impl Process { match self { Process::Managed(p) => packet_server::WvrProcess { name: p.get_name().unwrap_or(String::from("unknown")), + userdata: p.userdata.clone(), display_handle: p.display_handle.as_packet(), handle: handle.as_packet(), }, Process::External(p) => packet_server::WvrProcess { name: p.get_name().unwrap_or(String::from("unknown")), + userdata: Default::default(), display_handle: p.display_handle.as_packet(), handle: handle.as_packet(), }, diff --git a/src/backend/wayvr/server_ipc.rs b/src/backend/wayvr/server_ipc.rs index 1ebc309..0b7b95a 100644 --- a/src/backend/wayvr/server_ipc.rs +++ b/src/backend/wayvr/server_ipc.rs @@ -1,4 +1,4 @@ -use super::{display, process, TickTask, WayVRSignal}; +use super::{display, process, window, TickTask, WayVRSignal}; use bytes::BufMut; use interprocess::local_socket::{self, traits::Listener, ToNsName}; use smallvec::SmallVec; @@ -236,6 +236,97 @@ impl Connection { Ok(()) } + fn handle_wvr_display_set_window_layout( + &mut self, + params: &mut TickParams, + handle: packet_server::WvrDisplayHandle, + layout: packet_server::WvrDisplayWindowLayout, + ) -> anyhow::Result<()> { + params.state.signals.send(WayVRSignal::DisplayWindowLayout( + display::DisplayHandle::from_packet(handle), + layout, + )); + Ok(()) + } + + fn handle_wvr_display_window_list( + &mut self, + params: &mut TickParams, + serial: ipc::Serial, + display_handle: packet_server::WvrDisplayHandle, + ) -> anyhow::Result<()> { + let mut send = |list: Option| -> anyhow::Result<()> { + send_packet( + &mut self.conn, + &ipc::data_encode(&PacketServer::WvrDisplayWindowListResponse(serial, list)), + ) + }; + + let Some(display) = params + .state + .displays + .get(&display::DisplayHandle::from_packet(display_handle.clone())) + else { + return send(None); + }; + + send(Some(packet_server::WvrWindowList { + list: display + .displayed_windows + .iter() + .filter_map(|disp_win| { + params + .state + .wm + .borrow_mut() + .windows + .get(&disp_win.window_handle) + .map(|win| packet_server::WvrWindow { + handle: window::WindowHandle::as_packet(&disp_win.window_handle), + process_handle: process::ProcessHandle::as_packet( + &disp_win.process_handle, + ), + pos_x: win.pos_x, + pos_y: win.pos_y, + size_x: win.size_x, + size_y: win.size_y, + visible: win.visible, + display_handle: display_handle.clone(), + }) + }) + .collect::>(), + })) + } + + fn handle_wvr_window_set_visible( + &mut self, + params: &mut TickParams, + handle: packet_server::WvrWindowHandle, + visible: bool, + ) -> anyhow::Result<()> { + let mut to_resize = None; + + if let Some(window) = params + .state + .wm + .borrow_mut() + .windows + .get_mut(&window::WindowHandle::from_packet(handle)) + { + window.visible = visible; + to_resize = Some(window.display_handle); + } + + if let Some(to_resize) = to_resize { + if let Some(display) = params.state.displays.get_mut(&to_resize) { + display.reposition_windows(); + display.trigger_rerender(); + } + } + + Ok(()) + } + fn handle_wvr_process_launch( &mut self, params: &mut TickParams, @@ -250,6 +341,7 @@ impl Connection { &packet_params.exec, &args_vec, &env_vec, + packet_params.userdata, ); let res = res.map(|r| r.as_packet()).map_err(|e| e.to_string()); @@ -262,7 +354,7 @@ impl Connection { Ok(()) } - fn handle_wvr_process_get( + fn handle_wvr_display_get( &mut self, params: &TickParams, serial: ipc::Serial, @@ -332,6 +424,27 @@ impl Connection { Ok(()) } + fn handle_wvr_process_get( + &mut self, + params: &TickParams, + serial: ipc::Serial, + process_handle: packet_server::WvrProcessHandle, + ) -> anyhow::Result<()> { + let native_handle = &process::ProcessHandle::from_packet(process_handle.clone()); + let process = params + .state + .processes + .get(native_handle) + .map(|process| process.to_packet(*native_handle)); + + send_packet( + &mut self.conn, + &ipc::data_encode(&PacketServer::WvrProcessGetResponse(serial, process)), + )?; + + Ok(()) + } + fn handle_wlx_haptics( &mut self, params: &mut TickParams, @@ -362,7 +475,7 @@ impl Connection { self.handle_wvr_display_list(params, serial)?; } PacketClient::WvrDisplayGet(serial, display_handle) => { - self.handle_wvr_process_get(params, serial, display_handle)?; + self.handle_wvr_display_get(params, serial, display_handle)?; } PacketClient::WvrDisplayRemove(serial, display_handle) => { self.handle_wvr_display_remove(params, serial, display_handle)?; @@ -370,6 +483,18 @@ impl Connection { PacketClient::WvrDisplaySetVisible(display_handle, visible) => { self.handle_wvr_display_set_visible(params, display_handle, visible)?; } + PacketClient::WvrDisplaySetWindowLayout(display_handle, layout) => { + self.handle_wvr_display_set_window_layout(params, display_handle, layout)?; + } + PacketClient::WvrDisplayWindowList(serial, display_handle) => { + self.handle_wvr_display_window_list(params, serial, display_handle)?; + } + PacketClient::WvrWindowSetVisible(window_handle, visible) => { + self.handle_wvr_window_set_visible(params, window_handle, visible)?; + } + PacketClient::WvrProcessGet(serial, process_handle) => { + self.handle_wvr_process_get(params, serial, process_handle)?; + } PacketClient::WvrProcessList(serial) => { self.handle_wvr_process_list(params, serial)?; } @@ -507,4 +632,11 @@ impl WayVRServer { self.tick_connections(params); Ok(()) } + + pub fn broadcast(&mut self, packet: packet_server::PacketServer) -> anyhow::Result<()> { + for connection in &mut self.connections { + send_packet(&mut connection.conn, &ipc::data_encode(&packet))?; + } + Ok(()) + } } diff --git a/src/backend/wayvr/window.rs b/src/backend/wayvr/window.rs index 787c5e2..6466303 100644 --- a/src/backend/wayvr/window.rs +++ b/src/backend/wayvr/window.rs @@ -1,24 +1,31 @@ use smithay::wayland::shell::xdg::ToplevelSurface; +use wayvr_ipc::packet_server; use crate::gen_id; +use super::display; + #[derive(Debug)] pub struct Window { pub pos_x: i32, pub pos_y: i32, pub size_x: u32, pub size_y: u32, + pub visible: bool, pub toplevel: ToplevelSurface, + pub display_handle: display::DisplayHandle, } impl Window { - pub fn new(toplevel: &ToplevelSurface) -> Self { + pub fn new(display_handle: display::DisplayHandle, toplevel: &ToplevelSurface) -> Self { Self { pos_x: 0, pos_y: 0, size_x: 0, size_y: 0, + visible: true, toplevel: toplevel.clone(), + display_handle, } } @@ -63,9 +70,29 @@ impl WindowManager { None } - pub fn create_window(&mut self, toplevel: &ToplevelSurface) -> WindowHandle { - self.windows.add(Window::new(toplevel)) + pub fn create_window( + &mut self, + display_handle: display::DisplayHandle, + toplevel: &ToplevelSurface, + ) -> WindowHandle { + self.windows.add(Window::new(display_handle, toplevel)) } } gen_id!(WindowVec, Window, WindowCell, WindowHandle); + +impl WindowHandle { + pub fn from_packet(handle: packet_server::WvrWindowHandle) -> Self { + Self { + generation: handle.generation, + idx: handle.idx, + } + } + + pub fn as_packet(&self) -> packet_server::WvrWindowHandle { + packet_server::WvrWindowHandle { + idx: self.idx, + generation: self.generation, + } + } +} diff --git a/src/overlays/wayvr.rs b/src/overlays/wayvr.rs index 82cc86c..ccf4de9 100644 --- a/src/overlays/wayvr.rs +++ b/src/overlays/wayvr.rs @@ -1,6 +1,7 @@ use glam::{vec3a, Affine2, Vec3, Vec3A}; use std::{cell::RefCell, collections::HashMap, rc::Rc, sync::Arc}; use vulkano::image::SubresourceLayout; +use wayvr_ipc::packet_server; use wlx_capture::frame::{DmabufFrame, FourCC, FrameFormat, FramePlane}; use crate::{ @@ -309,12 +310,17 @@ where None => vec![], }; + let mut userdata = HashMap::new(); + userdata.insert(String::from("type"), String::from("dashboard")); + // Start dashboard specified in the WayVR config - let _process_handle_unused = - wayvr - .data - .state - .spawn_process(disp_handle, &conf_dash.exec, &args_vec, &env_vec)?; + let _process_handle_unused = wayvr.data.state.spawn_process( + disp_handle, + &conf_dash.exec, + &args_vec, + &env_vec, + userdata, + )?; wayvr.dashboard_executed = true; @@ -434,6 +440,15 @@ where )); } } + 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))?; + } } } @@ -734,10 +749,13 @@ where wayvr.data.terminate_process(process_handle); } else { // Spawn process - wayvr - .data - .state - .spawn_process(disp_handle, &app_entry.exec, &args_vec, &env_vec)?; + wayvr.data.state.spawn_process( + disp_handle, + &app_entry.exec, + &args_vec, + &env_vec, + Default::default(), + )?; show_display::(&mut wayvr, overlays, app_entry.target_display.as_str()); }