WayVR: Haptics support, fix warnings, EGL fix, display visibility IPC, bump dashboard resolution to 1080p

This commit is contained in:
Aleksander
2025-01-23 20:26:34 +01:00
parent 5d9f80ea40
commit 8766999e28
12 changed files with 77 additions and 41 deletions

2
Cargo.lock generated
View File

@@ -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",

View File

@@ -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]

View File

@@ -241,6 +241,7 @@ pub struct PointerHit {
pub dist: f32,
}
#[derive(Clone)]
pub struct Haptics {
pub intensity: f32,
pub duration: f32,

View File

@@ -135,7 +135,7 @@ impl LinePool {
&'a mut self,
xr: &'a XrState,
command_buffer: &mut WlxCommandBuffer,
) -> anyhow::Result<Vec<CompositionLayer>> {
) -> anyhow::Result<Vec<CompositionLayer<'a>>> {
let mut quads = Vec::new();
for line in self.lines.values_mut() {

View File

@@ -27,7 +27,7 @@ impl OverlayData<OpenXrOverlayData> {
&'a mut self,
xr: &'a XrState,
command_buffer: &mut WlxCommandBuffer,
) -> anyhow::Result<CompositionLayer> {
) -> anyhow::Result<CompositionLayer<'a>> {
if let Some(new_view) = self.view() {
self.data.last_view = Some(new_view);
}

View File

@@ -74,7 +74,7 @@ impl Skybox {
xr: &'a XrState,
hmd: Affine3A,
command_buffer: &mut WlxCommandBuffer,
) -> anyhow::Result<Vec<CompositionLayer>> {
) -> anyhow::Result<Vec<CompositionLayer<'a>>> {
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 {

View File

@@ -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,

View File

@@ -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));
}
}
}

View File

@@ -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<khronos_egl::Image> {
pub fn create_egl_image(&self, gl_tex_id: u32) -> anyhow::Result<khronos_egl::Image> {
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],
)?)
}
}

View File

@@ -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<display::DisplayHandle>,
tasks: SyncEventQueue<WayVRTask>,
pub tasks: SyncEventQueue<WayVRTask>,
pub signals: SyncEventQueue<WayVRSignal>,
ticks: u64,
pub pending_haptic: Option<super::input::Haptics>,
}
pub struct WayVR {
pub state: WayVRState,
ipc_server: WayVRServer,
pub signals: SyncEventQueue<WayVRSignal>,
}
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);
}
}
}

View File

@@ -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(())

View File

@@ -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;
}),
));
}