get rid of wayvr refcell

This commit is contained in:
galister
2025-12-27 13:27:44 +09:00
parent d70b51184c
commit 35f3748b95
11 changed files with 156 additions and 175 deletions

View File

@@ -74,6 +74,7 @@ impl compositor::CompositorHandler for Application {
&client.get_data::<ClientState>().unwrap().compositor_state &client.get_data::<ClientState>().unwrap().compositor_state
} }
#[allow(clippy::significant_drop_tightening)]
fn commit(&mut self, surface: &WlSurface) { fn commit(&mut self, surface: &WlSurface) {
smithay::wayland::compositor::with_states(surface, |states| { smithay::wayland::compositor::with_states(surface, |states| {
let mut guard = states.cached_state.get::<SurfaceAttributes>(); let mut guard = states.cached_state.get::<SurfaceAttributes>();
@@ -88,7 +89,7 @@ impl compositor::CompositorHandler for Application {
.image_importer .image_importer
.get_or_import_dmabuf(dmabuf.clone()) .get_or_import_dmabuf(dmabuf.clone())
.inspect_err(|e| { .inspect_err(|e| {
log::warn!("wayland_server failed to import DMA-buf: {e:?}") log::warn!("wayland_server failed to import DMA-buf: {e:?}");
}) })
{ {
let sbwi = SurfaceBufWithImage { let sbwi = SurfaceBufWithImage {
@@ -108,7 +109,7 @@ impl compositor::CompositorHandler for Application {
.image_importer .image_importer
.import_shm(data, size, buf) .import_shm(data, size, buf)
.inspect_err(|e| { .inspect_err(|e| {
log::warn!("wayland_server failed to import SHM: {e:?}") log::warn!("wayland_server failed to import SHM: {e:?}");
}) })
{ {
let sbwi = SurfaceBufWithImage { let sbwi = SurfaceBufWithImage {
@@ -127,7 +128,7 @@ impl compositor::CompositorHandler for Application {
let spb = get_single_pixel_buffer(&buffer).unwrap(); // always Ok let spb = get_single_pixel_buffer(&buffer).unwrap(); // always Ok
if let Ok(image) = if let Ok(image) =
self.image_importer.import_spb(spb).inspect_err(|e| { self.image_importer.import_spb(spb).inspect_err(|e| {
log::warn!("wayland_server failed to import SPB: {e:?}") log::warn!("wayland_server failed to import SPB: {e:?}");
}) })
{ {
let sbwi = SurfaceBufWithImage { let sbwi = SurfaceBufWithImage {
@@ -147,8 +148,7 @@ impl compositor::CompositorHandler for Application {
} }
buffer.release(); buffer.release();
} }
Some(BufferAssignment::Removed) => {} Some(BufferAssignment::Removed) | None => {}
None => {}
} }
let t = time::get_millis() as u32; let t = time::get_millis() as u32;
@@ -299,7 +299,7 @@ delegate_seat!(Application);
delegate_data_device!(Application); delegate_data_device!(Application);
delegate_output!(Application); delegate_output!(Application);
fn wl_transform_to_frame_transform( const fn wl_transform_to_frame_transform(
transform: wl_output::Transform, transform: wl_output::Transform,
) -> wlx_capture::frame::Transform { ) -> wlx_capture::frame::Transform {
match transform { match transform {

View File

@@ -25,6 +25,7 @@ use smithay::{
use std::{ use std::{
cell::RefCell, cell::RefCell,
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
rc::Rc,
sync::Arc, sync::Arc,
time::{Duration, Instant}, time::{Duration, Instant},
}; };
@@ -106,7 +107,7 @@ pub struct Config {
pub blit_method: BlitMethod, pub blit_method: BlitMethod,
} }
pub struct WayVRState { pub struct WvrServerState {
time_start: u64, time_start: u64,
pub manager: client::WayVRCompositor, pub manager: client::WayVRCompositor,
pub wm: window::WindowManager, pub wm: window::WindowManager,
@@ -131,8 +132,7 @@ pub enum TickTask {
NewExternalProcess(ExternalProcessRequest), // Call WayVRCompositor::add_client after receiving this message NewExternalProcess(ExternalProcessRequest), // Call WayVRCompositor::add_client after receiving this message
} }
impl WayVRState { impl WvrServerState {
#[allow(clippy::too_many_lines, clippy::cognitive_complexity)]
pub fn new( pub fn new(
gfx: Arc<WGfx>, gfx: Arc<WGfx>,
gfx_extras: &WGfxExtras, gfx_extras: &WGfxExtras,
@@ -180,8 +180,8 @@ impl WayVRState {
// this will throw a compile-time error if smithay's drm-fourcc is out of sync with wlx-capture's // this will throw a compile-time error if smithay's drm-fourcc is out of sync with wlx-capture's
let mut formats: Vec<smithay::backend::allocator::Format> = vec![]; let mut formats: Vec<smithay::backend::allocator::Format> = vec![];
for f in gfx_extras.drm_formats.iter() { for f in &gfx_extras.drm_formats {
formats.push(f.clone()); formats.push(*f);
} }
let dmabuf_state = DmabufFeedbackBuilder::new(main_device, formats.clone()) let dmabuf_state = DmabufFeedbackBuilder::new(main_device, formats.clone())
@@ -230,7 +230,7 @@ impl WayVRState {
let time_start = get_millis(); let time_start = get_millis();
Ok(WayVRState { Ok(Self {
time_start, time_start,
manager: client::WayVRCompositor::new(state, display, seat_keyboard, seat_pointer)?, manager: client::WayVRCompositor::new(state, display, seat_keyboard, seat_pointer)?,
processes: ProcessVec::new(), processes: ProcessVec::new(),
@@ -246,12 +246,16 @@ impl WayVRState {
}) })
} }
#[allow(clippy::too_many_lines, clippy::cognitive_complexity)] #[allow(clippy::too_many_lines)]
pub fn tick_events(&mut self, app: &mut AppState) -> anyhow::Result<Vec<TickTask>> { pub fn tick_events(app: &mut AppState) -> anyhow::Result<Vec<TickTask>> {
let mut tasks: Vec<TickTask> = Vec::new(); let mut tasks: Vec<TickTask> = Vec::new();
let Some(wvr_server) = app.wvr_server.as_mut() else {
return Ok(tasks);
};
app.ipc_server.tick(&mut ipc_server::TickParams { app.ipc_server.tick(&mut ipc_server::TickParams {
wayland_state: self, wvr_server,
input_state: &app.input_state, input_state: &app.input_state,
tasks: &mut tasks, tasks: &mut tasks,
signals: &app.wayvr_signals, signals: &app.wayvr_signals,
@@ -260,14 +264,14 @@ impl WayVRState {
// Tick all child processes // Tick all child processes
let mut to_remove: SmallVec<[process::ProcessHandle; 2]> = SmallVec::new(); let mut to_remove: SmallVec<[process::ProcessHandle; 2]> = SmallVec::new();
for (handle, process) in self.processes.iter_mut() { for (handle, process) in wvr_server.processes.iter_mut() {
if !process.is_running() { if !process.is_running() {
to_remove.push(handle); to_remove.push(handle);
} }
} }
for p_handle in &to_remove { for p_handle in &to_remove {
self.processes.remove(p_handle); wvr_server.processes.remove(p_handle);
} }
if !to_remove.is_empty() { if !to_remove.is_empty() {
@@ -276,20 +280,22 @@ impl WayVRState {
)); ));
} }
while let Some(task) = self.tasks.read() { while let Some(task) = wvr_server.tasks.read() {
match task { match task {
WayVRTask::NewExternalProcess(req) => { WayVRTask::NewExternalProcess(req) => {
tasks.push(TickTask::NewExternalProcess(req)); tasks.push(TickTask::NewExternalProcess(req));
} }
WayVRTask::NewToplevel(client_id, toplevel) => { WayVRTask::NewToplevel(client_id, toplevel) => {
let toplevel = Rc::new(toplevel);
// Attach newly created toplevel surfaces to displays // Attach newly created toplevel surfaces to displays
for client in &self.manager.clients { for client in &wvr_server.manager.clients {
if client.client.id() != client_id { if client.client.id() != client_id {
continue; continue;
} }
let Some(process_handle) = let Some(process_handle) =
process::find_by_pid(&self.processes, client.pid) process::find_by_pid(&wvr_server.processes, client.pid)
else { else {
log::error!( log::error!(
"WayVR window creation failed: Unexpected process ID {}. It wasn't registered before.", "WayVR window creation failed: Unexpected process ID {}. It wasn't registered before.",
@@ -298,32 +304,26 @@ impl WayVRState {
continue; continue;
}; };
let window_handle = self.wm.create_window(&toplevel, process_handle); let window_handle = wvr_server
.wm
.create_window(toplevel.clone(), process_handle);
let title: Arc<str> = with_states(toplevel.wl_surface(), |states| { let title: Arc<str> = with_states(toplevel.wl_surface(), |states| {
states states
.data_map .data_map
.get::<XdgToplevelSurfaceData>() .get::<XdgToplevelSurfaceData>()
.and_then(|t| t.lock().unwrap().title.clone()) .and_then(|t| t.lock().unwrap().title.clone())
.map(|t| t.into()) .map_or_else(|| format!("P{}", client.pid).into(), String::into)
.unwrap_or_else(|| format!("P{}", client.pid).into())
}); });
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Create( app.tasks.enqueue(TaskType::Overlay(OverlayTask::Create(
OverlaySelector::Nothing, OverlaySelector::Nothing,
Box::new(move |app: &mut AppState| { Box::new(move |app: &mut AppState| {
Some( Some(create_wl_window_overlay(
create_wl_window_overlay(
title, title,
app.xr_backend, app.xr_backend,
app.wayvr_server.as_ref().unwrap().clone(),
window_handle, window_handle,
) ))
.inspect_err(|e| {
log::error!("Could not add wayland client overlay: {e:?}")
})
.ok()?,
)
}), }),
))); )));
@@ -333,28 +333,29 @@ impl WayVRState {
} }
} }
WayVRTask::DropToplevel(client_id, toplevel) => { WayVRTask::DropToplevel(client_id, toplevel) => {
for client in &self.manager.clients { for client in &wvr_server.manager.clients {
if client.client.id() != client_id { if client.client.id() != client_id {
continue; continue;
} }
let Some(window_handle) = self.wm.find_window_handle(&toplevel) else { let Some(window_handle) = wvr_server.wm.find_window_handle(&toplevel)
else {
log::warn!("DropToplevel: Couldn't find matching window handle"); log::warn!("DropToplevel: Couldn't find matching window handle");
continue; continue;
}; };
if let Some(oid) = self.window_to_overlay.remove(&window_handle) { if let Some(oid) = wvr_server.window_to_overlay.remove(&window_handle) {
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Drop( app.tasks.enqueue(TaskType::Overlay(OverlayTask::Drop(
OverlaySelector::Id(oid), OverlaySelector::Id(oid),
))); )));
self.overlay_to_window.remove(oid); wvr_server.overlay_to_window.remove(oid);
} }
self.wm.remove_window(window_handle); wvr_server.wm.remove_window(window_handle);
} }
} }
WayVRTask::ProcessTerminationRequest(process_handle) => { WayVRTask::ProcessTerminationRequest(process_handle) => {
if let Some(process) = self.processes.get_mut(&process_handle) { if let Some(process) = wvr_server.processes.get_mut(&process_handle) {
process.terminate(); process.terminate();
} }
@@ -363,14 +364,14 @@ impl WayVRState {
} }
} }
self.manager.tick_wayland(&mut self.processes)?; wvr_server.manager.tick_wayland(&mut wvr_server.processes)?;
if self.ticks.is_multiple_of(200) { if wvr_server.ticks.is_multiple_of(200) {
self.manager.cleanup_clients(); wvr_server.manager.cleanup_clients();
self.manager.cleanup_handles(); wvr_server.manager.cleanup_handles();
} }
self.ticks += 1; wvr_server.ticks += 1;
Ok(tasks) Ok(tasks)
} }
@@ -396,7 +397,7 @@ impl WayVRState {
} }
self.mouse_freeze = Instant::now() + Duration::from_millis(1); // prevent other pointer from moving the mouse on the same frame self.mouse_freeze = Instant::now() + Duration::from_millis(1); // prevent other pointer from moving the mouse on the same frame
self.wm.mouse = Some(window::MouseState { self.wm.mouse = Some(window::MouseState {
hover_window: handle.clone(), hover_window: handle,
x, x,
y, y,
}); });

View File

@@ -1,3 +1,5 @@
use std::rc::Rc;
use smithay::{ use smithay::{
input, input,
utils::{Logical, Point}, utils::{Logical, Point},
@@ -16,17 +18,17 @@ pub struct Window {
pub size_x: u32, pub size_x: u32,
pub size_y: u32, pub size_y: u32,
pub visible: bool, pub visible: bool,
pub toplevel: ToplevelSurface, pub toplevel: Rc<ToplevelSurface>,
pub process: process::ProcessHandle, pub process: process::ProcessHandle,
} }
impl Window { impl Window {
fn new(toplevel: &ToplevelSurface, process: process::ProcessHandle) -> Self { const fn new(toplevel: Rc<ToplevelSurface>, process: process::ProcessHandle) -> Self {
Self { Self {
size_x: 0, size_x: 0,
size_y: 0, size_y: 0,
visible: true, visible: true,
toplevel: toplevel.clone(), toplevel,
process, process,
} }
} }
@@ -152,7 +154,7 @@ impl WindowManager {
for (idx, cell) in self.windows.vec.iter().enumerate() { for (idx, cell) in self.windows.vec.iter().enumerate() {
if let Some(cell) = cell { if let Some(cell) = cell {
let window = &cell.obj; let window = &cell.obj;
if window.toplevel == *toplevel { if *window.toplevel == *toplevel {
return Some(WindowVec::get_handle(cell, idx)); return Some(WindowVec::get_handle(cell, idx));
} }
} }
@@ -162,7 +164,7 @@ impl WindowManager {
pub fn create_window( pub fn create_window(
&mut self, &mut self,
toplevel: &ToplevelSurface, toplevel: Rc<ToplevelSurface>,
process: process::ProcessHandle, process: process::ProcessHandle,
) -> WindowHandle { ) -> WindowHandle {
self.windows.add(Window::new(toplevel, process)) self.windows.add(Window::new(toplevel, process))

View File

@@ -2,9 +2,7 @@
compile_error!("WayVR feature is not enabled"); compile_error!("WayVR feature is not enabled");
use std::{ use std::{
cell::RefCell,
collections::{BTreeMap, HashMap}, collections::{BTreeMap, HashMap},
rc::Rc,
sync::Arc, sync::Arc,
}; };
@@ -16,7 +14,7 @@ use wlx_common::{common::LeftRight, config::GeneralConfig, windowing::Positionin
use crate::{ use crate::{
backend::{ backend::{
task::TaskContainer, task::TaskContainer,
wayvr::{self, WayVRState}, wayvr::{self, WvrServerState},
}, },
config::load_config_with_conf_d, config::load_config_with_conf_d,
config_io, config_io,
@@ -203,9 +201,9 @@ impl WayVRConfig {
gfx: Arc<WGfx>, gfx: Arc<WGfx>,
gfx_extras: &WGfxExtras, gfx_extras: &WGfxExtras,
config: &GeneralConfig, config: &GeneralConfig,
tasks: &mut TaskContainer, _tasks: &mut TaskContainer,
signals: SyncEventQueue<WayVRSignal>, signals: SyncEventQueue<WayVRSignal>,
) -> anyhow::Result<Rc<RefCell<WayVRState>>> { ) -> anyhow::Result<WvrServerState> {
let primary_count = self let primary_count = self
.displays .displays
.iter() .iter()
@@ -216,7 +214,7 @@ impl WayVRConfig {
anyhow::bail!("Number of primary displays is more than 1") anyhow::bail!("Number of primary displays is more than 1")
} }
for (catalog_name, catalog) in &self.catalogs { for (_catalog_name, catalog) in &self.catalogs {
for app in &catalog.apps { for app in &catalog.apps {
if let Some(b) = app.shown_at_start if let Some(b) = app.shown_at_start
&& b && b
@@ -226,12 +224,12 @@ impl WayVRConfig {
} }
} }
Ok(Rc::new(RefCell::new(WayVRState::new( WvrServerState::new(
gfx, gfx,
gfx_extras, gfx_extras,
Self::get_wayvr_config(config, self)?, Self::get_wayvr_config(config, self)?,
signals, signals,
)?))) )
} }
} }

View File

@@ -347,7 +347,8 @@ pub(super) fn setup_custom_button<S: 'static>(
return Ok(EventResult::Pass); return Ok(EventResult::Pass);
} }
app.hid_provider.send_key_routed(key, down); app.hid_provider
.send_key_routed(app.wvr_server.as_mut(), key, down);
Ok(EventResult::Consumed) Ok(EventResult::Consumed)
}) })
} }

View File

@@ -1,9 +1,7 @@
use std::{cell::RefCell, rc::Rc};
use wayvr_ipc::packet_server; use wayvr_ipc::packet_server;
#[cfg(feature = "wayvr")] #[cfg(feature = "wayvr")]
use crate::backend::wayvr::{self, WayVRState}; use crate::backend::wayvr::{self, WvrServerState};
use crate::{ use crate::{
backend::{ backend::{
@@ -18,18 +16,14 @@ use crate::{
#[cfg(feature = "wayvr")] #[cfg(feature = "wayvr")]
fn process_tick_tasks( fn process_tick_tasks(
tick_tasks: Vec<backend::wayvr::TickTask>, tick_tasks: Vec<backend::wayvr::TickTask>,
r_wayvr: &Rc<RefCell<WayVRState>>, server_state: &mut WvrServerState,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
for tick_task in tick_tasks { for tick_task in tick_tasks {
match tick_task { match tick_task {
backend::wayvr::TickTask::NewExternalProcess(request) => { backend::wayvr::TickTask::NewExternalProcess(request) => {
let mut wayvr = r_wayvr.borrow_mut();
log::info!("Registering external process with PID {}", request.pid); log::info!("Registering external process with PID {}", request.pid);
server_state.add_external_process(request.pid);
wayvr.add_external_process(request.pid); server_state.manager.add_client(wayvr::client::WayVRClient {
wayvr.manager.add_client(wayvr::client::WayVRClient {
client: request.client, client: request.client,
pid: request.pid, pid: request.pid,
}); });
@@ -47,9 +41,6 @@ pub fn tick_events<O>(
where where
O: Default, O: Default,
{ {
#[cfg(feature = "wayvr")]
let wayvr_server = app.wayvr_server.clone();
while let Some(signal) = app.wayvr_signals.read() { while let Some(signal) = app.wayvr_signals.read() {
match signal { match signal {
#[cfg(feature = "wayvr")] #[cfg(feature = "wayvr")]
@@ -76,9 +67,9 @@ where
#[cfg(feature = "wayvr")] #[cfg(feature = "wayvr")]
{ {
if let Some(wayvr_server) = wayvr_server { let tick_tasks = WvrServerState::tick_events(app)?;
let tick_tasks = wayvr_server.borrow_mut().tick_events(app)?; if let Some(wayvr_server) = app.wvr_server.as_mut() {
process_tick_tasks(tick_tasks, &wayvr_server)?; process_tick_tasks(tick_tasks, wayvr_server)?;
} }
} }

View File

@@ -1,5 +1,5 @@
#[cfg(feature = "wayvr")] #[cfg(feature = "wayvr")]
use crate::backend::wayvr::{self, WayVRState}; use crate::backend::wayvr::{self, WvrServerState};
use crate::{ use crate::{
backend::input::InputState, backend::input::InputState,
@@ -76,7 +76,7 @@ fn read_payload(conn: &mut local_socket::Stream, size: u32) -> Option<Payload> {
pub struct TickParams<'a> { pub struct TickParams<'a> {
#[cfg(feature = "wayvr")] #[cfg(feature = "wayvr")]
pub wayland_state: &'a mut WayVRState, pub wvr_server: &'a mut WvrServerState,
#[cfg(feature = "wayvr")] #[cfg(feature = "wayvr")]
pub tasks: &'a mut Vec<wayvr::TickTask>, pub tasks: &'a mut Vec<wayvr::TickTask>,
pub signals: &'a SyncEventQueue<WayVRSignal>, pub signals: &'a SyncEventQueue<WayVRSignal>,
@@ -197,7 +197,7 @@ impl Connection {
send(Some(packet_server::WvrWindowList { send(Some(packet_server::WvrWindowList {
list: params list: params
.wayland_state .wvr_server
.wm .wm
.windows .windows
.iter() .iter()
@@ -219,7 +219,7 @@ impl Connection {
visible: bool, visible: bool,
) { ) {
if let Some(window) = params if let Some(window) = params
.wayland_state .wvr_server
.wm .wm
.windows .windows
.get_mut(&wayvr::window::WindowHandle::from_packet(handle)) .get_mut(&wayvr::window::WindowHandle::from_packet(handle))
@@ -238,7 +238,7 @@ 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.wayland_state.spawn_process( let res = params.wvr_server.spawn_process(
&packet_params.exec, &packet_params.exec,
&args_vec, &args_vec,
&env_vec, &env_vec,
@@ -263,7 +263,7 @@ impl Connection {
serial: ipc::Serial, serial: ipc::Serial,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let list: Vec<packet_server::WvrProcess> = params let list: Vec<packet_server::WvrProcess> = params
.wayland_state .wvr_server
.processes .processes
.vec .vec
.iter() .iter()
@@ -298,7 +298,7 @@ impl Connection {
process_handle: packet_server::WvrProcessHandle, process_handle: packet_server::WvrProcessHandle,
) { ) {
let native_handle = &wayvr::process::ProcessHandle::from_packet(process_handle); let native_handle = &wayvr::process::ProcessHandle::from_packet(process_handle);
let process = params.wayland_state.processes.get_mut(native_handle); let process = params.wvr_server.processes.get_mut(native_handle);
let Some(process) = process else { let Some(process) = process else {
return; return;
@@ -316,7 +316,7 @@ impl Connection {
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let native_handle = &wayvr::process::ProcessHandle::from_packet(process_handle); let native_handle = &wayvr::process::ProcessHandle::from_packet(process_handle);
let process = params let process = params
.wayland_state .wvr_server
.processes .processes
.get(native_handle) .get(native_handle)
.map(|process| process.to_packet(*native_handle)); .map(|process| process.to_packet(*native_handle));

View File

@@ -85,7 +85,8 @@ pub fn create_keyboard(app: &mut AppState, wayland: bool) -> anyhow::Result<Over
.ok(); .ok();
if let Some(keymap) = maybe_keymap.as_ref() { if let Some(keymap) = maybe_keymap.as_ref() {
app.hid_provider.keymap_changed(keymap); app.hid_provider
.keymap_changed(app.wvr_server.as_mut(), keymap);
} }
if !auto_labels { if !auto_labels {
@@ -218,7 +219,8 @@ impl KeyboardBackend {
fn auto_switch_keymap(&mut self, app: &mut AppState) -> anyhow::Result<bool> { fn auto_switch_keymap(&mut self, app: &mut AppState) -> anyhow::Result<bool> {
let keymap = self.get_effective_keymap(app)?; let keymap = self.get_effective_keymap(app)?;
app.hid_provider.keymap_changed(&keymap); app.hid_provider
.keymap_changed(app.wvr_server.as_mut(), &keymap);
self.switch_keymap(&keymap, app) self.switch_keymap(&keymap, app)
} }
@@ -258,7 +260,8 @@ impl OverlayBackend for KeyboardBackend {
} }
fn pause(&mut self, app: &mut AppState) -> anyhow::Result<()> { fn pause(&mut self, app: &mut AppState) -> anyhow::Result<()> {
self.panel().state.modifiers = 0; self.panel().state.modifiers = 0;
app.hid_provider.set_modifiers_routed(0); app.hid_provider
.set_modifiers_routed(app.wvr_server.as_mut(), 0);
self.panel().pause(app) self.panel().pause(app)
} }
fn resume(&mut self, app: &mut AppState) -> anyhow::Result<()> { fn resume(&mut self, app: &mut AppState) -> anyhow::Result<()> {
@@ -371,20 +374,24 @@ fn handle_press(
_ => 0, _ => 0,
}; };
app.hid_provider.set_modifiers_routed(keyboard.modifiers); app.hid_provider
app.hid_provider.send_key_routed(*vk, true); .set_modifiers_routed(app.wvr_server.as_mut(), keyboard.modifiers);
app.hid_provider
.send_key_routed(app.wvr_server.as_mut(), *vk, true);
pressed.set(true); pressed.set(true);
play_key_click(app); play_key_click(app);
} }
KeyButtonData::Modifier { modifier, sticky } => { KeyButtonData::Modifier { modifier, sticky } => {
sticky.set(keyboard.modifiers & *modifier == 0); sticky.set(keyboard.modifiers & *modifier == 0);
keyboard.modifiers |= *modifier; keyboard.modifiers |= *modifier;
app.hid_provider.set_modifiers_routed(keyboard.modifiers); app.hid_provider
.set_modifiers_routed(app.wvr_server.as_mut(), keyboard.modifiers);
play_key_click(app); play_key_click(app);
} }
KeyButtonData::Macro { verbs } => { KeyButtonData::Macro { verbs } => {
for (vk, press) in verbs { for (vk, press) in verbs {
app.hid_provider.send_key_routed(*vk, *press); app.hid_provider
.send_key_routed(app.wvr_server.as_mut(), *vk, *press);
} }
play_key_click(app); play_key_click(app);
} }
@@ -412,8 +419,10 @@ fn handle_release(app: &mut AppState, key: &KeyState, keyboard: &mut KeyboardSta
keyboard.modifiers &= !*m; keyboard.modifiers &= !*m;
} }
} }
app.hid_provider.send_key_routed(*vk, false); app.hid_provider
app.hid_provider.set_modifiers_routed(keyboard.modifiers); .send_key_routed(app.wvr_server.as_mut(), *vk, false);
app.hid_provider
.set_modifiers_routed(app.wvr_server.as_mut(), keyboard.modifiers);
true true
} }
KeyButtonData::Modifier { modifier, sticky } => { KeyButtonData::Modifier { modifier, sticky } => {
@@ -421,7 +430,8 @@ fn handle_release(app: &mut AppState, key: &KeyState, keyboard: &mut KeyboardSta
false false
} else { } else {
keyboard.modifiers &= !*modifier; keyboard.modifiers &= !*modifier;
app.hid_provider.set_modifiers_routed(keyboard.modifiers); app.hid_provider
.set_modifiers_routed(app.wvr_server.as_mut(), keyboard.modifiers);
true true
} }
} }

View File

@@ -1,6 +1,6 @@
use glam::{Affine2, Affine3A, Quat, Vec3, vec3}; use glam::{Affine2, Affine3A, Quat, Vec3, vec3};
use smithay::wayland::compositor::with_states; use smithay::wayland::compositor::with_states;
use std::{cell::RefCell, rc::Rc, sync::Arc}; use std::sync::Arc;
use vulkano::image::view::ImageView; use vulkano::image::view::ImageView;
use wlx_capture::frame::MouseMeta; use wlx_capture::frame::MouseMeta;
use wlx_common::{ use wlx_common::{
@@ -12,7 +12,7 @@ use crate::{
backend::{ backend::{
XrBackend, XrBackend,
input::{self, HoverResult}, input::{self, HoverResult},
wayvr::{self, SurfaceBufWithImage, WayVRState}, wayvr::{self, SurfaceBufWithImage},
}, },
graphics::ExtentExt, graphics::ExtentExt,
overlays::screen::capture::ScreenPipeline, overlays::screen::capture::ScreenPipeline,
@@ -30,10 +30,9 @@ use crate::{
pub fn create_wl_window_overlay( pub fn create_wl_window_overlay(
name: Arc<str>, name: Arc<str>,
xr_backend: XrBackend, xr_backend: XrBackend,
wayvr: Rc<RefCell<WayVRState>>,
window: wayvr::window::WindowHandle, window: wayvr::window::WindowHandle,
) -> anyhow::Result<OverlayWindowConfig> { ) -> OverlayWindowConfig {
Ok(OverlayWindowConfig { OverlayWindowConfig {
name: name.clone(), name: name.clone(),
default_state: OverlayWindowState { default_state: OverlayWindowState {
grabbable: true, grabbable: true,
@@ -50,35 +49,32 @@ pub fn create_wl_window_overlay(
keyboard_focus: Some(KeyboardFocus::WayVR), keyboard_focus: Some(KeyboardFocus::WayVR),
category: OverlayCategory::WayVR, category: OverlayCategory::WayVR,
show_on_spawn: true, show_on_spawn: true,
..OverlayWindowConfig::from_backend(Box::new(WayVRBackend::new( ..OverlayWindowConfig::from_backend(Box::new(WvrWindowBackend::new(
name, xr_backend, wayvr, window, name, xr_backend, window,
)?)) )))
}) }
} }
pub struct WayVRBackend { pub struct WvrWindowBackend {
name: Arc<str>, name: Arc<str>,
pipeline: Option<ScreenPipeline>, pipeline: Option<ScreenPipeline>,
interaction_transform: Option<Affine2>, interaction_transform: Option<Affine2>,
window: wayvr::window::WindowHandle, window: wayvr::window::WindowHandle,
wayvr: Rc<RefCell<WayVRState>>,
just_resumed: bool, just_resumed: bool,
meta: Option<FrameMeta>, meta: Option<FrameMeta>,
stereo: Option<StereoMode>, stereo: Option<StereoMode>,
cur_image: Option<Arc<ImageView>>, cur_image: Option<Arc<ImageView>>,
} }
impl WayVRBackend { impl WvrWindowBackend {
fn new( const fn new(
name: Arc<str>, name: Arc<str>,
xr_backend: XrBackend, xr_backend: XrBackend,
wayvr: Rc<RefCell<WayVRState>>,
window: wayvr::window::WindowHandle, window: wayvr::window::WindowHandle,
) -> anyhow::Result<Self> { ) -> Self {
Ok(Self { Self {
name, name,
pipeline: None, pipeline: None,
wayvr,
window, window,
interaction_transform: None, interaction_transform: None,
just_resumed: false, just_resumed: false,
@@ -89,11 +85,11 @@ impl WayVRBackend {
None None
}, },
cur_image: None, cur_image: None,
}) }
} }
} }
impl OverlayBackend for WayVRBackend { impl OverlayBackend for WvrWindowBackend {
fn init(&mut self, _app: &mut state::AppState) -> anyhow::Result<()> { fn init(&mut self, _app: &mut state::AppState) -> anyhow::Result<()> {
Ok(()) Ok(())
} }
@@ -108,8 +104,12 @@ impl OverlayBackend for WayVRBackend {
} }
fn should_render(&mut self, app: &mut AppState) -> anyhow::Result<ShouldRender> { fn should_render(&mut self, app: &mut AppState) -> anyhow::Result<ShouldRender> {
let wayvr = &self.wayvr.borrow(); let Some(toplevel) = app
let Some(window) = wayvr.wm.windows.get(&self.window) else { .wvr_server
.as_ref()
.and_then(|sv| sv.wm.windows.get(&self.window))
.map(|win| win.toplevel.clone())
else {
log::debug!( log::debug!(
"{:?}: WayVR overlay without matching window entry", "{:?}: WayVR overlay without matching window entry",
self.name self.name
@@ -117,7 +117,7 @@ impl OverlayBackend for WayVRBackend {
return Ok(ShouldRender::Unable); return Ok(ShouldRender::Unable);
}; };
with_states(window.toplevel.wl_surface(), |states| { with_states(toplevel.wl_surface(), |states| {
if let Some(surf) = SurfaceBufWithImage::get_from_surface(states) { if let Some(surf) = SurfaceBufWithImage::get_from_surface(states) {
let mut meta = FrameMeta { let mut meta = FrameMeta {
extent: surf.image.image().extent(), extent: surf.image.image().extent(),
@@ -174,8 +174,8 @@ impl OverlayBackend for WayVRBackend {
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let image = self.cur_image.as_ref().unwrap().clone(); let image = self.cur_image.as_ref().unwrap().clone();
let wayvr = &self.wayvr.borrow(); let wvr_server = app.wvr_server.as_mut().unwrap(); //never None
let mouse = wayvr let mouse = wvr_server
.wm .wm
.mouse .mouse
.as_ref() .as_ref()
@@ -202,23 +202,23 @@ impl OverlayBackend for WayVRBackend {
fn notify( fn notify(
&mut self, &mut self,
_app: &mut state::AppState, app: &mut state::AppState,
event_data: OverlayEventData, event_data: OverlayEventData,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
if let OverlayEventData::IdAssigned(oid) = event_data { if let OverlayEventData::IdAssigned(oid) = event_data {
let wayvr = &mut self.wayvr.borrow_mut(); let wvr_server = app.wvr_server.as_mut().unwrap(); //never None
wayvr.overlay_added(oid, self.window.clone()); wvr_server.overlay_added(oid, self.window.clone());
} }
Ok(()) Ok(())
} }
fn on_hover(&mut self, _app: &mut state::AppState, hit: &input::PointerHit) -> HoverResult { fn on_hover(&mut self, app: &mut state::AppState, hit: &input::PointerHit) -> HoverResult {
let wayvr = &mut self.wayvr.borrow_mut();
if let Some(meta) = self.meta.as_ref() { if let Some(meta) = self.meta.as_ref() {
let x = ((hit.uv.x * (meta.extent[0] as f32)) as u32).max(0); let x = ((hit.uv.x * (meta.extent[0] as f32)) as u32).max(0);
let y = ((hit.uv.y * (meta.extent[1] as f32)) as u32).max(0); let y = ((hit.uv.y * (meta.extent[1] as f32)) as u32).max(0);
wayvr.send_mouse_move(self.window, x, y);
let wvr_server = app.wvr_server.as_mut().unwrap(); //never None
wvr_server.send_mouse_move(self.window, x, y);
} }
HoverResult { HoverResult {
@@ -231,7 +231,7 @@ impl OverlayBackend for WayVRBackend {
// Ignore event // Ignore event
} }
fn on_pointer(&mut self, _app: &mut state::AppState, hit: &input::PointerHit, pressed: bool) { fn on_pointer(&mut self, app: &mut state::AppState, hit: &input::PointerHit, pressed: bool) {
if let Some(index) = match hit.mode { if let Some(index) = match hit.mode {
input::PointerMode::Left => Some(wayvr::MouseIndex::Left), input::PointerMode::Left => Some(wayvr::MouseIndex::Left),
input::PointerMode::Middle => Some(wayvr::MouseIndex::Center), input::PointerMode::Middle => Some(wayvr::MouseIndex::Center),
@@ -241,22 +241,23 @@ impl OverlayBackend for WayVRBackend {
None None
} }
} { } {
let wayvr = &mut self.wayvr.borrow_mut(); let wvr_server = app.wvr_server.as_mut().unwrap(); //never None
if pressed { if pressed {
wayvr.send_mouse_down(self.window, index); wvr_server.send_mouse_down(self.window, index);
} else { } else {
wayvr.send_mouse_up(index); wvr_server.send_mouse_up(index);
} }
} }
} }
fn on_scroll( fn on_scroll(
&mut self, &mut self,
_app: &mut state::AppState, app: &mut state::AppState,
_hit: &input::PointerHit, _hit: &input::PointerHit,
delta: WheelDelta, delta: WheelDelta,
) { ) {
self.wayvr.borrow_mut().send_mouse_scroll(delta); let wvr_server = app.wvr_server.as_mut().unwrap(); //never None
wvr_server.send_mouse_scroll(delta);
} }
fn get_interaction_transform(&mut self) -> Option<Affine2> { fn get_interaction_transform(&mut self) -> Option<Affine2> {

View File

@@ -12,13 +12,10 @@ use wlx_common::{
}; };
#[cfg(feature = "wayvr")] #[cfg(feature = "wayvr")]
use { use crate::config_wayvr::{self, WayVRConfig};
crate::config_wayvr::{self, WayVRConfig},
std::{cell::RefCell, rc::Rc},
};
#[cfg(feature = "wayvr")] #[cfg(feature = "wayvr")]
use crate::backend::wayvr::WayVRState; use crate::backend::wayvr::WvrServerState;
#[cfg(feature = "osc")] #[cfg(feature = "osc")]
use crate::subsystem::osc::OscSender; use crate::subsystem::osc::OscSender;
@@ -62,7 +59,7 @@ pub struct AppState {
pub osc_sender: Option<OscSender>, pub osc_sender: Option<OscSender>,
#[cfg(feature = "wayvr")] #[cfg(feature = "wayvr")]
pub wayvr_server: Option<Rc<RefCell<WayVRState>>>, pub wvr_server: Option<WvrServerState>,
} }
#[allow(unused_mut)] #[allow(unused_mut)]
@@ -93,11 +90,6 @@ impl AppState {
let mut hid_provider = HidWrapper::new(); let mut hid_provider = HidWrapper::new();
#[cfg(feature = "wayvr")]
if let Some(wayland_server) = wayvr_server.as_ref() {
hid_provider.set_wayvr(wayland_server.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();
@@ -158,7 +150,7 @@ impl AppState {
osc_sender, osc_sender,
#[cfg(feature = "wayvr")] #[cfg(feature = "wayvr")]
wayvr_server, wvr_server: wayvr_server,
}) })
} }

View File

@@ -1,25 +1,19 @@
use super::hid::{self, HidProvider, VirtualKey}; use super::hid::{self, HidProvider, VirtualKey};
#[cfg(feature = "wayvr")] use crate::{backend::wayvr::WvrServerState, subsystem::hid::XkbKeymap};
use crate::backend::wayvr::WayVRState;
use crate::subsystem::hid::XkbKeymap;
#[cfg(feature = "wayvr")]
use std::{cell::RefCell, rc::Rc};
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum KeyboardFocus { pub enum KeyboardFocus {
PhysicalScreen, PhysicalScreen,
#[allow(dead_code)] // Not available if "wayvr" feature is disabled #[allow(dead_code)] // Not available if "wayvr" feature is disabled
WayVR, // (for now without wayland window id data, it's handled internally), WayVR, // (wayland window id data is handled internally),
} }
pub struct HidWrapper { pub struct HidWrapper {
pub keyboard_focus: KeyboardFocus, pub keyboard_focus: KeyboardFocus,
pub inner: Box<dyn HidProvider>, pub inner: Box<dyn HidProvider>,
pub keymap: Option<XkbKeymap>, pub keymap: Option<XkbKeymap>,
#[cfg(feature = "wayvr")]
pub wayvr: Option<Rc<RefCell<WayVRState>>>, // Dynamically created if requested
} }
impl HidWrapper { impl HidWrapper {
@@ -27,41 +21,32 @@ impl HidWrapper {
Self { Self {
keyboard_focus: KeyboardFocus::PhysicalScreen, keyboard_focus: KeyboardFocus::PhysicalScreen,
inner: hid::initialize(), inner: hid::initialize(),
#[cfg(feature = "wayvr")]
wayvr: None,
keymap: None, keymap: None,
} }
} }
#[cfg(feature = "wayvr")] pub fn send_key_routed(
pub fn set_wayvr(&mut self, wayvr: Rc<RefCell<WayVRState>>) { &self,
if let Some(keymap) = self.keymap.take() { wvr_server: Option<&mut WvrServerState>,
let _ = wayvr key: VirtualKey,
.borrow_mut() down: bool,
.set_keymap(&keymap.inner) ) {
.inspect_err(|e| log::error!("Could not set WayVR keymap: {e:?}"));
}
self.wayvr = Some(wayvr);
}
pub fn send_key_routed(&self, key: VirtualKey, down: bool) {
match self.keyboard_focus { match self.keyboard_focus {
KeyboardFocus::PhysicalScreen => self.inner.send_key(key, down), KeyboardFocus::PhysicalScreen => self.inner.send_key(key, down),
KeyboardFocus::WayVR => KeyboardFocus::WayVR =>
{ {
#[cfg(feature = "wayvr")] #[cfg(feature = "wayvr")]
if let Some(wayvr) = &self.wayvr { if let Some(wvr_server) = wvr_server {
wayvr.borrow_mut().send_key(key as u32, down); wvr_server.send_key(key as u32, down);
} }
} }
} }
} }
pub fn keymap_changed(&mut self, keymap: &XkbKeymap) { pub fn keymap_changed(&mut self, wvr_server: Option<&mut WvrServerState>, keymap: &XkbKeymap) {
#[cfg(feature = "wayvr")] #[cfg(feature = "wayvr")]
if let Some(wayvr) = &self.wayvr { if let Some(wvr_server) = wvr_server {
let _ = wayvr let _ = wvr_server
.borrow_mut()
.set_keymap(&keymap.inner) .set_keymap(&keymap.inner)
.inspect_err(|e| log::error!("Could not set WayVR keymap: {e:?}")); .inspect_err(|e| log::error!("Could not set WayVR keymap: {e:?}"));
} else { } else {
@@ -74,14 +59,14 @@ impl HidWrapper {
); );
} }
pub fn set_modifiers_routed(&mut self, mods: u8) { pub fn set_modifiers_routed(&mut self, wvr_server: Option<&mut WvrServerState>, mods: u8) {
match self.keyboard_focus { match self.keyboard_focus {
KeyboardFocus::PhysicalScreen => self.inner.set_modifiers(mods), KeyboardFocus::PhysicalScreen => self.inner.set_modifiers(mods),
KeyboardFocus::WayVR => KeyboardFocus::WayVR =>
{ {
#[cfg(feature = "wayvr")] #[cfg(feature = "wayvr")]
if let Some(wayvr) = &self.wayvr { if let Some(wvr_server) = wvr_server {
wayvr.borrow_mut().set_modifiers(mods); wvr_server.set_modifiers(mods);
} }
} }
} }