diff --git a/Cargo.lock b/Cargo.lock index 6b82e58..5807430 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=94ab6125ec07c091099bf71b028d701b58eccccf#94ab6125ec07c091099bf71b028d701b58eccccf" +source = "git+https://github.com/olekolek1000/wayvr-ipc.git?rev=fe2e8be04c7b86adcf972be7ebe46961bd881f35#fe2e8be04c7b86adcf972be7ebe46961bd881f35" dependencies = [ "anyhow", "bytes", diff --git a/Cargo.toml b/Cargo.toml index 83dea61..ef5178e 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 = "94ab6125ec07c091099bf71b028d701b58eccccf", default-features = false, optional = true } +wayvr_ipc = { git = "https://github.com/olekolek1000/wayvr-ipc.git", rev = "fe2e8be04c7b86adcf972be7ebe46961bd881f35", default-features = false, optional = true } ################################ [build-dependencies] diff --git a/src/backend/input.rs b/src/backend/input.rs index 7d05352..8383c9c 100644 --- a/src/backend/input.rs +++ b/src/backend/input.rs @@ -241,6 +241,7 @@ pub struct PointerHit { pub dist: f32, } +#[derive(Clone)] pub struct Haptics { pub intensity: f32, pub duration: f32, diff --git a/src/backend/openxr/lines.rs b/src/backend/openxr/lines.rs index e2f703e..173182b 100644 --- a/src/backend/openxr/lines.rs +++ b/src/backend/openxr/lines.rs @@ -135,7 +135,7 @@ impl LinePool { &'a mut self, xr: &'a XrState, command_buffer: &mut WlxCommandBuffer, - ) -> anyhow::Result> { + ) -> anyhow::Result>> { let mut quads = Vec::new(); for line in self.lines.values_mut() { diff --git a/src/backend/openxr/overlay.rs b/src/backend/openxr/overlay.rs index 7ed2857..9679d62 100644 --- a/src/backend/openxr/overlay.rs +++ b/src/backend/openxr/overlay.rs @@ -27,7 +27,7 @@ impl OverlayData { &'a mut self, xr: &'a XrState, command_buffer: &mut WlxCommandBuffer, - ) -> anyhow::Result { + ) -> anyhow::Result> { if let Some(new_view) = self.view() { self.data.last_view = Some(new_view); } diff --git a/src/backend/openxr/skybox.rs b/src/backend/openxr/skybox.rs index adaa255..9346507 100644 --- a/src/backend/openxr/skybox.rs +++ b/src/backend/openxr/skybox.rs @@ -74,7 +74,7 @@ impl Skybox { xr: &'a XrState, hmd: Affine3A, command_buffer: &mut WlxCommandBuffer, - ) -> anyhow::Result> { + ) -> anyhow::Result>> { let (sky_image, grid_image) = if let Some((ref mut srd_sky, ref mut srd_grid)) = self.srd { (srd_sky.present_last()?, srd_grid.present_last()?) } else { diff --git a/src/backend/overlay.rs b/src/backend/overlay.rs index 2f9b356..0a7097e 100644 --- a/src/backend/overlay.rs +++ b/src/backend/overlay.rs @@ -32,7 +32,8 @@ pub const Z_ORDER_TOAST: u32 = 70; pub const Z_ORDER_LINES: u32 = 69; pub const Z_ORDER_WATCH: u32 = 68; pub const Z_ORDER_ANCHOR: u32 = 67; -pub const Z_ORDER_DASHBOARD: u32 = 66; +pub const Z_ORDER_DEFAULT: u32 = 0; +pub const Z_ORDER_DASHBOARD: u32 = Z_ORDER_DEFAULT; pub struct OverlayState { pub id: OverlayID, @@ -73,7 +74,7 @@ impl Default for OverlayState { keyboard_focus: None, dirty: true, alpha: 1.0, - z_order: 0, + z_order: Z_ORDER_DEFAULT, relative_to: RelativeTo::None, curvature: None, spawn_scale: 1.0, diff --git a/src/backend/wayvr/display.rs b/src/backend/wayvr/display.rs index f42c767..f1b5624 100644 --- a/src/backend/wayvr/display.rs +++ b/src/backend/wayvr/display.rs @@ -124,7 +124,7 @@ impl Display { ) })?; - let egl_image = egl_data.create_egl_image(tex_id, width as u32, height as u32)?; + let egl_image = egl_data.create_egl_image(tex_id)?; let dmabuf_data = egl_data.create_dmabuf_data(&egl_image)?; let opaque = false; @@ -207,7 +207,8 @@ impl Display { } else if let Some(auto_hide_delay) = config.auto_hide_delay { if let Some(s) = self.no_windows_since { if s + (auto_hide_delay as u64) < get_millis() { - signals.send(WayVRSignal::DisplayHideRequest(*handle)); + // Auto-hide after specific time + signals.send(WayVRSignal::DisplayVisibility(*handle, false)); } } } diff --git a/src/backend/wayvr/egl_data.rs b/src/backend/wayvr/egl_data.rs index 7842fd3..8653778 100644 --- a/src/backend/wayvr/egl_data.rs +++ b/src/backend/wayvr/egl_data.rs @@ -45,7 +45,9 @@ impl EGLData { let display = egl .get_display(khronos_egl::DEFAULT_DISPLAY) - .ok_or(anyhow!("eglGetDisplay failed"))?; + .ok_or(anyhow!( + "eglGetDisplay failed. This shouldn't happen unless you don't have any display manager running. Cannot continue, check your EGL installation." + ))?; let (major, minor) = egl.initialize(display)?; log::debug!("EGL version: {}.{}", major, minor); @@ -242,25 +244,14 @@ impl EGLData { } } - pub fn create_egl_image( - &self, - gl_tex_id: u32, - width: u32, - height: u32, - ) -> anyhow::Result { + pub fn create_egl_image(&self, gl_tex_id: u32) -> anyhow::Result { unsafe { Ok(self.egl.create_image( self.display, self.context, khronos_egl::GL_TEXTURE_2D as std::ffi::c_uint, khronos_egl::ClientBuffer::from_ptr(gl_tex_id as *mut std::ffi::c_void), - &[ - khronos_egl::WIDTH as usize, - width as usize, - khronos_egl::HEIGHT as usize, - height as usize, - khronos_egl::ATTRIB_NONE, - ], + &[khronos_egl::ATTRIB_NONE], )?) } } diff --git a/src/backend/wayvr/mod.rs b/src/backend/wayvr/mod.rs index 7807ad0..eb5a4da 100644 --- a/src/backend/wayvr/mod.rs +++ b/src/backend/wayvr/mod.rs @@ -70,11 +70,12 @@ pub enum WayVRTask { NewExternalProcess(ExternalProcessRequest), DropOverlay(super::overlay::OverlayID), ProcessTerminationRequest(process::ProcessHandle), + Haptics(super::input::Haptics), } #[derive(Clone)] pub enum WayVRSignal { - DisplayHideRequest(display::DisplayHandle), + DisplayVisibility(display::DisplayHandle, bool), } pub struct Config { @@ -93,14 +94,15 @@ pub struct WayVRState { pub processes: process::ProcessVec, config: Config, dashboard_display: Option, - tasks: SyncEventQueue, + pub tasks: SyncEventQueue, + pub signals: SyncEventQueue, ticks: u64, + pub pending_haptic: Option, } pub struct WayVR { pub state: WayVRState, ipc_server: WayVRServer, - pub signals: SyncEventQueue, } pub enum MouseIndex { @@ -235,13 +237,11 @@ impl WayVR { dashboard_display: None, ticks: 0, tasks, + pending_haptic: None, + signals: SyncEventQueue::new(), }; - Ok(Self { - state, - signals: SyncEventQueue::new(), - ipc_server, - }) + Ok(Self { state, ipc_server }) } pub fn tick_display(&mut self, display: display::DisplayHandle) -> anyhow::Result<()> { @@ -314,7 +314,7 @@ impl WayVR { } self.state.displays.iter_mut(&mut |handle, display| { - display.tick(&self.state.config, &handle, &mut self.signals); + display.tick(&self.state.config, &handle, &mut self.state.signals); }); while let Some(task) = self.state.tasks.read() { @@ -358,6 +358,9 @@ impl WayVR { process.terminate(); } } + WayVRTask::Haptics(haptics) => { + self.state.pending_haptic = Some(haptics); + } } } diff --git a/src/backend/wayvr/server_ipc.rs b/src/backend/wayvr/server_ipc.rs index a624526..1ebc309 100644 --- a/src/backend/wayvr/server_ipc.rs +++ b/src/backend/wayvr/server_ipc.rs @@ -1,4 +1,4 @@ -use super::{display, process, TickTask}; +use super::{display, process, TickTask, WayVRSignal}; use bytes::BufMut; use interprocess::local_socket::{self, traits::Listener, ToNsName}; use smallvec::SmallVec; @@ -223,6 +223,19 @@ impl Connection { Ok(()) } + fn handle_wvr_display_set_visible( + &mut self, + params: &mut TickParams, + handle: packet_server::WvrDisplayHandle, + visible: bool, + ) -> anyhow::Result<()> { + params.state.signals.send(WayVRSignal::DisplayVisibility( + display::DisplayHandle::from_packet(handle), + visible, + )); + Ok(()) + } + fn handle_wvr_process_launch( &mut self, params: &mut TickParams, @@ -319,6 +332,22 @@ impl Connection { Ok(()) } + fn handle_wlx_haptics( + &mut self, + params: &mut TickParams, + haptics_params: packet_client::WlxHapticsParams, + ) -> anyhow::Result<()> { + params + .state + .tasks + .send(super::WayVRTask::Haptics(crate::backend::input::Haptics { + duration: haptics_params.duration, + frequency: haptics_params.frequency, + intensity: haptics_params.intensity, + })); + Ok(()) + } + fn process_payload(&mut self, params: &mut TickParams, payload: Payload) -> anyhow::Result<()> { let packet: PacketClient = ipc::data_decode(&payload)?; @@ -338,6 +367,9 @@ impl Connection { PacketClient::WvrDisplayRemove(serial, display_handle) => { self.handle_wvr_display_remove(params, serial, display_handle)?; } + PacketClient::WvrDisplaySetVisible(display_handle, visible) => { + self.handle_wvr_display_set_visible(params, display_handle, visible)?; + } PacketClient::WvrProcessList(serial) => { self.handle_wvr_process_list(params, serial)?; } @@ -350,6 +382,9 @@ impl Connection { PacketClient::WvrProcessTerminate(process_handle) => { self.handle_wvr_process_terminate(params, process_handle)?; } + PacketClient::WlxHaptics(haptics_params) => { + self.handle_wlx_haptics(params, haptics_params)?; + } } Ok(()) diff --git a/src/overlays/wayvr.rs b/src/overlays/wayvr.rs index 1de6959..82cc86c 100644 --- a/src/overlays/wayvr.rs +++ b/src/overlays/wayvr.rs @@ -27,8 +27,8 @@ use crate::{ use super::toast::error_toast; // Hard-coded for now -const DASHBOARD_WIDTH: u16 = 960; -const DASHBOARD_HEIGHT: u16 = 540; +const DASHBOARD_WIDTH: u16 = 1920; +const DASHBOARD_HEIGHT: u16 = 1080; const DASHBOARD_DISPLAY_NAME: &str = "_DASHBOARD"; pub struct WayVRContext { @@ -125,7 +125,7 @@ impl InteractionHandler for WayVRInteractionHandler { wayvr.state.send_mouse_move(ctx.display, x as u32, y as u32); } - None + wayvr.state.pending_haptic.take() } fn on_left(&mut self, _app: &mut state::AppState, _pointer: usize) { @@ -280,7 +280,8 @@ where )?; overlay.state.want_visible = true; - overlay.state.spawn_scale = 1.25; + overlay.state.spawn_scale = 2.0; + overlay.state.spawn_point = vec3a(0.0, -0.35, -1.75); overlay.state.z_order = Z_ORDER_DASHBOARD; overlay.state.reset(app, true); @@ -416,16 +417,19 @@ where let mut wayvr = r_wayvr.borrow_mut(); - while let Some(signal) = wayvr.data.signals.read() { + while let Some(signal) = wayvr.data.state.signals.read() { match signal { - wayvr::WayVRSignal::DisplayHideRequest(display_handle) => { + 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, false); + wayvr + .data + .state + .set_display_visible(display_handle, visible); app.tasks.enqueue(TaskType::Overlay( OverlaySelector::Id(overlay_id), Box::new(move |_app, o| { - o.want_visible = false; + o.want_visible = visible; }), )); }