Merge pull request #146 from olekolek1000/wayvr_dashboard_ipc
WayVR: Layouting system, state changing feedback, process userdata, various IPC changes
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -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",
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -334,7 +334,11 @@ pub fn openvr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
|
||||
};
|
||||
|
||||
#[cfg(feature = "wayvr")]
|
||||
crate::overlays::wayvr::tick_events::<OpenVrOverlayData>(&mut state, &mut overlays)?;
|
||||
if let Err(e) =
|
||||
crate::overlays::wayvr::tick_events::<OpenVrOverlayData>(&mut state, &mut overlays)
|
||||
{
|
||||
log::error!("WayVR tick_events failed: {:?}", e);
|
||||
}
|
||||
|
||||
log::trace!("Rendering frame");
|
||||
|
||||
|
||||
@@ -382,7 +382,11 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
|
||||
}
|
||||
|
||||
#[cfg(feature = "wayvr")]
|
||||
crate::overlays::wayvr::tick_events::<OpenXrOverlayData>(&mut app_state, &mut overlays)?;
|
||||
if let Err(e) =
|
||||
crate::overlays::wayvr::tick_events::<OpenXrOverlayData>(&mut app_state, &mut overlays)
|
||||
{
|
||||
log::error!("WayVR tick_events failed: {:?}", e);
|
||||
}
|
||||
|
||||
for o in overlays.iter_mut() {
|
||||
if !o.state.want_visible {
|
||||
|
||||
@@ -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<OverlayID>,
|
||||
pub wants_redraw: bool,
|
||||
pub primary: bool,
|
||||
@@ -84,29 +85,31 @@ impl Drop for Display {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DisplayInitParams<'a> {
|
||||
pub wm: Rc<RefCell<window::WindowManager>>,
|
||||
pub renderer: &'a mut GlesRenderer,
|
||||
pub egl_data: Rc<egl_data::EGLData>,
|
||||
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<RefCell<window::WindowManager>>,
|
||||
renderer: &mut GlesRenderer,
|
||||
egl_data: Rc<egl_data::EGLData>,
|
||||
wayland_env: super::WaylandEnv,
|
||||
width: u16,
|
||||
height: u16,
|
||||
name: &str,
|
||||
primary: bool,
|
||||
) -> anyhow::Result<Self> {
|
||||
if width > MAX_DISPLAY_SIZE {
|
||||
pub fn new(params: DisplayInitParams) -> anyhow::Result<Self> {
|
||||
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,11 +183,17 @@ 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() {
|
||||
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;
|
||||
|
||||
@@ -191,6 +202,43 @@ impl Display {
|
||||
|
||||
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, 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<window::WindowHandle> {
|
||||
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 {
|
||||
if self.visible == visible {
|
||||
return;
|
||||
}
|
||||
self.visible = visible;
|
||||
if visible {
|
||||
self.wants_redraw = true;
|
||||
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(
|
||||
|
||||
@@ -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<egl_data::DMAbufData> {
|
||||
self.displays
|
||||
.get(&display)
|
||||
@@ -469,17 +501,24 @@ impl WayVRState {
|
||||
name: &str,
|
||||
primary: bool,
|
||||
) -> anyhow::Result<display::DisplayHandle> {
|
||||
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<String, String>,
|
||||
) -> anyhow::Result<process::ProcessHandle> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<String>,
|
||||
pub env: Vec<(String, String)>,
|
||||
|
||||
pub userdata: HashMap<String, String>,
|
||||
}
|
||||
|
||||
#[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(),
|
||||
},
|
||||
|
||||
@@ -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<packet_server::WvrWindowList>| -> 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::<Vec<_>>(),
|
||||
}))
|
||||
}
|
||||
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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::<O>(&mut wayvr, overlays, app_entry.target_display.as_str());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user