WayVR: Modify readme, Various improvements
- Add "Quick setup" and images in readme - Implement `click_freeze_time_ms` - Automatically show hidden display if AppClick has been triggered
This commit is contained in:
@@ -346,7 +346,7 @@ pub fn openvr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
|
||||
|
||||
#[cfg(feature = "wayvr")]
|
||||
if let Some(wayvr) = &state.wayvr {
|
||||
wayvr.borrow_mut().tick_finish()?;
|
||||
wayvr.borrow_mut().state.tick_finish()?;
|
||||
}
|
||||
|
||||
// chaperone
|
||||
|
||||
@@ -402,7 +402,7 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
|
||||
|
||||
#[cfg(feature = "wayvr")]
|
||||
if let Some(wayvr) = &app_state.wayvr {
|
||||
wayvr.borrow_mut().tick_finish()?;
|
||||
wayvr.borrow_mut().state.tick_finish()?;
|
||||
}
|
||||
|
||||
command_buffer.build_and_execute_now()?;
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
**WayVR acts as a bridge between Wayland applications and wlx-overlay-s panels, allowing you to display your applications within a VR environment. Internally, WayVR utilizes Smithay to run a Wayland compositor.**
|
||||
|
||||
# Features
|
||||
|
||||
- Display Wayland applications without GPU overhead (zero-copy via dma-buf)
|
||||
- Mouse input
|
||||
- Precision scrolling support
|
||||
- XWayland "support" via `cage`
|
||||
|
||||
# Supported hardware
|
||||
|
||||
### Confirmed working GPUs
|
||||
|
||||
- Navi 32 family: AMD Radeon RX 7800 XT **\***
|
||||
- Navi 23 family: AMD Radeon RX 6600 XT
|
||||
- Navi 21 family: AMD Radeon Pro W6800, AMD Radeon RX 6800 XT
|
||||
- Nvidia GTX 16 Series
|
||||
- _Your GPU here? (Let us know!)_
|
||||
|
||||
**\*** - With dmabuf modifier mitigation (probably Mesa bug)
|
||||
|
||||
# Supported software
|
||||
|
||||
- Basically all Qt applications (they work out of the box)
|
||||
- Most XWayland applications via `cage`
|
||||
|
||||
# Known issues
|
||||
|
||||
- Context menus are not functional in most cases yet
|
||||
|
||||
- Due to unknown circumstances, dma-buf textures may display various graphical glitches due to invalid dma-buf tiling modifier. Please report your GPU model when filing an issue. Alternatively, you can run wlx-overlay-s with `LIBGL_ALWAYS_SOFTWARE=1` to mitigate that (only the Smithay compositor will run in software renderer mode, wlx will still be accelerated).
|
||||
|
||||
- ~~Potential data race in the rendering pipeline - A texture could be displayed during the clear-and-blit process in the compositor, causing minor artifacts (no fence sync support yet).~~ happens on all overlays on a simulated Monado driver
|
||||
|
||||
- Even though some applications support Wayland, some still check for the `DISPLAY` environment variable and an available X11 server, throwing an error. This can be fixed by running `cage`.
|
||||
|
||||
- GNOME still insists on rendering client-side decorations instead of server-side ones. This results in all GTK applications looking odd due to additional window shadows. [Fix here, "Client-side decorations"](https://wiki.archlinux.org/title/GTK)
|
||||
@@ -201,7 +201,7 @@ fn export_display_number(display_num: u32) -> anyhow::Result<()> {
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|_| PathBuf::from("/tmp"));
|
||||
path.push("wayvr.disp");
|
||||
std::fs::write(path, format!("{}\n", display_num)).unwrap();
|
||||
std::fs::write(path, format!("{}\n", display_num))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ use crate::{backend::overlay::OverlayID, gen_id};
|
||||
|
||||
use super::{
|
||||
client::WayVRManager, comp::send_frames_surface_tree, egl_data, event_queue::SyncEventQueue,
|
||||
process, smithay_wrapper, window,
|
||||
process, smithay_wrapper, time, window,
|
||||
};
|
||||
|
||||
fn generate_auth_key() -> String {
|
||||
@@ -54,6 +54,7 @@ pub struct Display {
|
||||
wm: Rc<RefCell<window::WindowManager>>,
|
||||
pub displayed_windows: Vec<DisplayWindow>,
|
||||
wayland_env: super::WaylandEnv,
|
||||
last_pressed_time_ms: u64,
|
||||
|
||||
// Render data stuff
|
||||
gles_texture: GlesTexture, // TODO: drop texture
|
||||
@@ -121,6 +122,7 @@ impl Display {
|
||||
primary,
|
||||
overlay_id: None,
|
||||
tasks: SyncEventQueue::new(),
|
||||
last_pressed_time_ms: 0,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -250,7 +252,18 @@ impl Display {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_mouse_move(&self, manager: &mut WayVRManager, x: u32, y: u32) {
|
||||
pub fn send_mouse_move(
|
||||
&self,
|
||||
config: &super::Config,
|
||||
manager: &mut WayVRManager,
|
||||
x: u32,
|
||||
y: u32,
|
||||
) {
|
||||
let current_ms = time::get_millis();
|
||||
if self.last_pressed_time_ms + config.click_freeze_time_ms as u64 > current_ms {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(window_handle) = self.get_hovered_window(x, y) {
|
||||
let wm = self.wm.borrow();
|
||||
if let Some(window) = wm.windows.get(&window_handle) {
|
||||
@@ -283,10 +296,12 @@ impl Display {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_mouse_down(&self, manager: &mut WayVRManager, index: super::MouseIndex) {
|
||||
pub fn send_mouse_down(&mut self, manager: &mut WayVRManager, index: super::MouseIndex) {
|
||||
// Change keyboard focus to pressed window
|
||||
let loc = manager.seat_pointer.current_location();
|
||||
|
||||
self.last_pressed_time_ms = time::get_millis();
|
||||
|
||||
if let Some(window_handle) =
|
||||
self.get_hovered_window(loc.x.max(0.0) as u32, loc.y.max(0.0) as u32)
|
||||
{
|
||||
|
||||
@@ -3,30 +3,30 @@
|
||||
use std::{cell::RefCell, collections::VecDeque, rc::Rc};
|
||||
|
||||
struct Data<DataType> {
|
||||
queue: VecDeque<DataType>,
|
||||
queue: VecDeque<DataType>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SyncEventQueue<DataType> {
|
||||
data: Rc<RefCell<Data<DataType>>>,
|
||||
data: Rc<RefCell<Data<DataType>>>,
|
||||
}
|
||||
|
||||
impl<DataType> SyncEventQueue<DataType> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
data: Rc::new(RefCell::new(Data {
|
||||
queue: Default::default(),
|
||||
})),
|
||||
}
|
||||
}
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
data: Rc::new(RefCell::new(Data {
|
||||
queue: Default::default(),
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send(&self, message: DataType) {
|
||||
let mut data = self.data.borrow_mut();
|
||||
data.queue.push_back(message);
|
||||
}
|
||||
pub fn send(&self, message: DataType) {
|
||||
let mut data = self.data.borrow_mut();
|
||||
data.queue.push_back(message);
|
||||
}
|
||||
|
||||
pub fn read(&self) -> Option<DataType> {
|
||||
let mut data = self.data.borrow_mut();
|
||||
data.queue.pop_front()
|
||||
}
|
||||
pub fn read(&self) -> Option<DataType> {
|
||||
let mut data = self.data.borrow_mut();
|
||||
data.queue.pop_front()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ macro_rules! gen_id {
|
||||
}
|
||||
|
||||
//ThingHandle
|
||||
#[derive(Default, Clone, Copy, PartialEq)]
|
||||
#[derive(Default, Clone, Copy, PartialEq, Hash, Eq)]
|
||||
pub struct $handle_name {
|
||||
idx: u32,
|
||||
generation: u64,
|
||||
|
||||
@@ -65,6 +65,12 @@ pub enum WayVRTask {
|
||||
ProcessTerminationRequest(process::ProcessHandle),
|
||||
}
|
||||
|
||||
pub struct Config {
|
||||
pub click_freeze_time_ms: u32,
|
||||
pub keyboard_repeat_delay_ms: u32,
|
||||
pub keyboard_repeat_rate: u32,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct WayVR {
|
||||
time_start: u64,
|
||||
@@ -74,6 +80,7 @@ pub struct WayVR {
|
||||
wm: Rc<RefCell<window::WindowManager>>,
|
||||
egl_data: Rc<egl_data::EGLData>,
|
||||
pub processes: process::ProcessVec,
|
||||
config: Config,
|
||||
|
||||
tasks: SyncEventQueue<WayVRTask>,
|
||||
}
|
||||
@@ -89,7 +96,7 @@ pub enum TickResult {
|
||||
}
|
||||
|
||||
impl WayVR {
|
||||
pub fn new() -> anyhow::Result<Self> {
|
||||
pub fn new(config: Config) -> anyhow::Result<Self> {
|
||||
log::info!("Initializing WayVR");
|
||||
let display: wayland_server::Display<Application> = wayland_server::Display::new()?;
|
||||
let dh = display.handle();
|
||||
@@ -100,8 +107,11 @@ impl WayVR {
|
||||
let data_device = DataDeviceState::new::<Application>(&dh);
|
||||
let mut seat = seat_state.new_wl_seat(&dh, "wayvr");
|
||||
|
||||
// TODO: Keyboard repeat delay and rate?
|
||||
let seat_keyboard = seat.add_keyboard(Default::default(), 100, 100)?;
|
||||
let seat_keyboard = seat.add_keyboard(
|
||||
Default::default(),
|
||||
config.keyboard_repeat_delay_ms as i32,
|
||||
config.keyboard_repeat_rate as i32,
|
||||
)?;
|
||||
let seat_pointer = seat.add_pointer();
|
||||
|
||||
let tasks = SyncEventQueue::new();
|
||||
@@ -131,6 +141,7 @@ impl WayVR {
|
||||
egl_data: Rc::new(egl_data),
|
||||
wm: Rc::new(RefCell::new(window::WindowManager::new())),
|
||||
tasks,
|
||||
config,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -222,7 +233,7 @@ impl WayVR {
|
||||
}
|
||||
} else {
|
||||
log::error!(
|
||||
"WayVR window creation failed: Unexpected process PID {}. It wasn't registered before.",
|
||||
"WayVR window creation failed: Unexpected process ID {}. It wasn't registered before.",
|
||||
client.pid
|
||||
);
|
||||
}
|
||||
@@ -255,12 +266,12 @@ impl WayVR {
|
||||
|
||||
pub fn send_mouse_move(&mut self, display: display::DisplayHandle, x: u32, y: u32) {
|
||||
if let Some(display) = self.displays.get(&display) {
|
||||
display.send_mouse_move(&mut self.manager, x, y);
|
||||
display.send_mouse_move(&self.config, &mut self.manager, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_mouse_down(&mut self, display: display::DisplayHandle, index: MouseIndex) {
|
||||
if let Some(display) = self.displays.get(&display) {
|
||||
if let Some(display) = self.displays.get_mut(&display) {
|
||||
display.send_mouse_down(&mut self.manager, index);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user