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:
90
contrib/wayvr/README.md
Normal file
90
contrib/wayvr/README.md
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
<p align="center">
|
||||||
|
<img src="https://raw.githubusercontent.com/galister/wlx-overlay-s/refs/heads/guide/wayvr/logo.svg" height="120"/>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
**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.**
|
||||||
|
|
||||||
|
# >> Quick setup <<
|
||||||
|
|
||||||
|
#### Configure your applications list
|
||||||
|
|
||||||
|
Go to `src/res/wayvr.yaml` to configure your desired application list. This configuration file represents all currently available WayVR options. Feel free to adjust it to your liking.
|
||||||
|
|
||||||
|
#### Add WayVR Launcher to your watch
|
||||||
|
|
||||||
|
Copy `watch_wayvr_example.yaml` to `~/.config/wlxoverlay/watch.yaml`. This file contains pre-configured **WayVRLauncher** and **WayVRDisplayList** widget types. By default, the _default_catalog_ is used.
|
||||||
|
|
||||||
|
That's it; you're all set!
|
||||||
|
|
||||||
|
###### _Make sure you have `wayvr` feature enabled in Cargo.toml (enabled by default)_
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
# Overview
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- Display Wayland applications without GPU overhead (zero-copy via dma-buf)
|
||||||
|
- Mouse and keyboard input, with precision scrolling support
|
||||||
|
- Tested on AMD and Nvidia
|
||||||
|
|
||||||
|
### Supported software
|
||||||
|
|
||||||
|
- Basically all Qt applications (they work out of the box)
|
||||||
|
- Most XWayland applications via `cage`
|
||||||
|
|
||||||
|
### XWayland
|
||||||
|
|
||||||
|
WayVR does not have native XWayland support. You can run X11 applications (or these who require DISPLAY set) by wrapping them in a `cage` program, like so:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: "Xeyes"
|
||||||
|
target_display: "Disp1"
|
||||||
|
exec: "cage"
|
||||||
|
args: "xeyes -- -fg blue"
|
||||||
|
```
|
||||||
|
|
||||||
|
instead of:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: "Xeyes"
|
||||||
|
target_display: "Disp1"
|
||||||
|
exec: "xeyes"
|
||||||
|
args: "-fg blue"
|
||||||
|
```
|
||||||
|
|
||||||
|
in `wayvr.yaml` configuration file, in your desired catalog.
|
||||||
|
|
||||||
|
### Launching external apps inside WayVR
|
||||||
|
|
||||||
|
To launch your app externally:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
DISPLAY= WAYLAND_DISPLAY=wayland-$(cat $XDG_RUNTIME_DIR/wayvr.disp) yourapp
|
||||||
|
```
|
||||||
|
|
||||||
|
or (in the most cases):
|
||||||
|
|
||||||
|
```
|
||||||
|
DISPLAY= WAYLAND_DISPLAY=wayland-20 yourapp
|
||||||
|
```
|
||||||
|
|
||||||
|
Setting `DISPLAY` to an empty string forces various apps to use Wayland instead of X11.
|
||||||
|
|
||||||
|
# Troubleshooting
|
||||||
|
|
||||||
|
### My application doesn't launch but others do!
|
||||||
|
|
||||||
|
Even though some applications support Wayland, some still check for the `DISPLAY` environment variable and an available X11 server, throwing an error. This can also be fixed by running `cage` on top of them.
|
||||||
|
|
||||||
|
### Image corruption
|
||||||
|
|
||||||
|
dma-buf textures may display various graphical glitches due to unsupported dma-buf tiling modifiers between GLES<->Vulkan on Radeon RDNA3 graphics cards. Current situation: https://gitlab.freedesktop.org/mesa/mesa/-/issues/11629). Nvidia should work out of the box, without any isues. 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).
|
||||||
|
|
||||||
|
### Floating windows
|
||||||
|
|
||||||
|
Context menus are not functional in most cases yet, including drag & drop support.
|
||||||
|
|
||||||
|
### Forced window shadows in GTK
|
||||||
|
|
||||||
|
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)
|
||||||
195
contrib/wayvr/watch_wayvr_example.yaml
Normal file
195
contrib/wayvr/watch_wayvr_example.yaml
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
# looking to make changes?
|
||||||
|
# drop me in ~/.config/wlxoverlay/watch.yaml
|
||||||
|
#
|
||||||
|
|
||||||
|
width: 0.115
|
||||||
|
|
||||||
|
size: [400, 272]
|
||||||
|
|
||||||
|
elements:
|
||||||
|
# background panel
|
||||||
|
- type: Panel
|
||||||
|
rect: [0, 30, 400, 130]
|
||||||
|
corner_radius: 20
|
||||||
|
bg_color: "#24273a"
|
||||||
|
|
||||||
|
- type: Button
|
||||||
|
rect: [2, 162, 26, 36]
|
||||||
|
corner_radius: 4
|
||||||
|
font_size: 15
|
||||||
|
bg_color: "#c6a0f6"
|
||||||
|
fg_color: "#24273a"
|
||||||
|
text: "C"
|
||||||
|
click_up: # destroy if exists, otherwise create
|
||||||
|
- type: Window
|
||||||
|
target: settings
|
||||||
|
action: ShowUi # only triggers if not exists
|
||||||
|
- type: Window
|
||||||
|
target: settings
|
||||||
|
action: Destroy # only triggers if exists since before current frame
|
||||||
|
|
||||||
|
# Keyboard button
|
||||||
|
- type: Button
|
||||||
|
rect: [32, 162, 60, 36]
|
||||||
|
corner_radius: 4
|
||||||
|
font_size: 15
|
||||||
|
fg_color: "#24273a"
|
||||||
|
bg_color: "#a6da95"
|
||||||
|
text: Kbd
|
||||||
|
click_up:
|
||||||
|
- type: Overlay
|
||||||
|
target: "kbd"
|
||||||
|
action: ToggleVisible
|
||||||
|
long_click_up:
|
||||||
|
- type: Overlay
|
||||||
|
target: "kbd"
|
||||||
|
action: Reset
|
||||||
|
right_up:
|
||||||
|
- type: Overlay
|
||||||
|
target: "kbd"
|
||||||
|
action: ToggleImmovable
|
||||||
|
middle_up:
|
||||||
|
- type: Overlay
|
||||||
|
target: "kbd"
|
||||||
|
action: ToggleInteraction
|
||||||
|
scroll_up:
|
||||||
|
- type: Overlay
|
||||||
|
target: "kbd"
|
||||||
|
action:
|
||||||
|
Opacity: { delta: 0.025 }
|
||||||
|
scroll_down:
|
||||||
|
- type: Overlay
|
||||||
|
target: "kbd"
|
||||||
|
action:
|
||||||
|
Opacity: { delta: -0.025 }
|
||||||
|
|
||||||
|
# bottom row, of keyboard + overlays
|
||||||
|
- type: OverlayList
|
||||||
|
rect: [94, 160, 306, 40]
|
||||||
|
corner_radius: 4
|
||||||
|
font_size: 15
|
||||||
|
fg_color: "#cad3f5"
|
||||||
|
bg_color: "#1e2030"
|
||||||
|
layout: Horizontal
|
||||||
|
click_up: ToggleVisible
|
||||||
|
long_click_up: Reset
|
||||||
|
right_up: ToggleImmovable
|
||||||
|
middle_up: ToggleInteraction
|
||||||
|
scroll_up:
|
||||||
|
Opacity: { delta: 0.025 }
|
||||||
|
scroll_down:
|
||||||
|
Opacity: { delta: -0.025 }
|
||||||
|
|
||||||
|
- type: WayVRLauncher
|
||||||
|
rect: [0, 200, 400, 36]
|
||||||
|
corner_radius: 4
|
||||||
|
font_size: 15
|
||||||
|
fg_color: "#24273a"
|
||||||
|
bg_color: "#e590c4"
|
||||||
|
catalog_name: "default_catalog"
|
||||||
|
|
||||||
|
- type: WayVRDisplayList
|
||||||
|
rect: [0, 236, 400, 36]
|
||||||
|
corner_radius: 4
|
||||||
|
font_size: 15
|
||||||
|
fg_color: "#24273a"
|
||||||
|
bg_color: "#ca68a4"
|
||||||
|
|
||||||
|
# local clock
|
||||||
|
- type: Label
|
||||||
|
rect: [19, 90, 200, 50]
|
||||||
|
corner_radius: 4
|
||||||
|
font_size: 46 # Use 32 for 12-hour time
|
||||||
|
fg_color: "#cad3f5"
|
||||||
|
source: Clock
|
||||||
|
format: "%H:%M" # 23:59
|
||||||
|
#format: "%I:%M %p" # 11:59 PM
|
||||||
|
|
||||||
|
# local date
|
||||||
|
- type: Label
|
||||||
|
rect: [20, 117, 200, 20]
|
||||||
|
corner_radius: 4
|
||||||
|
font_size: 14
|
||||||
|
fg_color: "#cad3f5"
|
||||||
|
source: Clock
|
||||||
|
format: "%x" # local date representation
|
||||||
|
|
||||||
|
# local day-of-week
|
||||||
|
- type: Label
|
||||||
|
rect: [20, 137, 200, 50]
|
||||||
|
corner_radius: 4
|
||||||
|
font_size: 14
|
||||||
|
fg_color: "#cad3f5"
|
||||||
|
source: Clock
|
||||||
|
format: "%A" # Tuesday
|
||||||
|
#format: "%a" # Tue
|
||||||
|
|
||||||
|
# alt clock 1
|
||||||
|
- type: Label
|
||||||
|
rect: [210, 90, 200, 50]
|
||||||
|
corner_radius: 4
|
||||||
|
font_size: 24 # Use 18 for 12-hour time
|
||||||
|
fg_color: "#8bd5ca"
|
||||||
|
source: Clock
|
||||||
|
timezone: "Asia/Tokyo" # change TZ1 here
|
||||||
|
format: "%H:%M" # 23:59
|
||||||
|
#format: "%I:%M %p" # 11:59 PM
|
||||||
|
- type: Label
|
||||||
|
rect: [210, 60, 200, 50]
|
||||||
|
corner_radius: 4
|
||||||
|
font_size: 14
|
||||||
|
fg_color: "#8bd5ca"
|
||||||
|
source: Static
|
||||||
|
text: "Tokyo" # change TZ1 label here
|
||||||
|
|
||||||
|
# alt clock 2
|
||||||
|
- type: Label
|
||||||
|
rect: [210, 150, 200, 50]
|
||||||
|
corner_radius: 4
|
||||||
|
font_size: 24 # Use 18 for 12-hour time
|
||||||
|
fg_color: "#b7bdf8"
|
||||||
|
source: Clock
|
||||||
|
timezone: "America/Chicago" # change TZ2 here
|
||||||
|
format: "%H:%M" # 23:59
|
||||||
|
#format: "%I:%M %p" # 11:59 PM
|
||||||
|
- type: Label
|
||||||
|
rect: [210, 120, 200, 50]
|
||||||
|
corner_radius: 4
|
||||||
|
font_size: 14
|
||||||
|
fg_color: "#b7bdf8"
|
||||||
|
source: Static
|
||||||
|
text: "Chicago" # change TZ2 label here
|
||||||
|
|
||||||
|
# batteries
|
||||||
|
- type: BatteryList
|
||||||
|
rect: [0, 5, 400, 30]
|
||||||
|
corner_radius: 4
|
||||||
|
font_size: 16
|
||||||
|
fg_color: "#8bd5ca"
|
||||||
|
fg_color_low: "#B06060"
|
||||||
|
fg_color_charging: "#6080A0"
|
||||||
|
num_devices: 9
|
||||||
|
layout: Horizontal
|
||||||
|
low_threshold: 33
|
||||||
|
|
||||||
|
# volume buttons
|
||||||
|
- type: Button
|
||||||
|
rect: [315, 52, 70, 32]
|
||||||
|
corner_radius: 4
|
||||||
|
font_size: 13
|
||||||
|
fg_color: "#cad3f5"
|
||||||
|
bg_color: "#5b6078"
|
||||||
|
text: "Vol +"
|
||||||
|
click_down:
|
||||||
|
- type: Exec
|
||||||
|
command: ["pactl", "set-sink-volume", "@DEFAULT_SINK@", "+5%"]
|
||||||
|
- type: Button
|
||||||
|
rect: [315, 116, 70, 32]
|
||||||
|
corner_radius: 4
|
||||||
|
font_size: 13
|
||||||
|
fg_color: "#cad3f5"
|
||||||
|
bg_color: "#5b6078"
|
||||||
|
text: "Vol -"
|
||||||
|
click_down:
|
||||||
|
- type: Exec
|
||||||
|
command: ["pactl", "set-sink-volume", "@DEFAULT_SINK@", "-5%"]
|
||||||
@@ -346,7 +346,7 @@ pub fn openvr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
|
|||||||
|
|
||||||
#[cfg(feature = "wayvr")]
|
#[cfg(feature = "wayvr")]
|
||||||
if let Some(wayvr) = &state.wayvr {
|
if let Some(wayvr) = &state.wayvr {
|
||||||
wayvr.borrow_mut().tick_finish()?;
|
wayvr.borrow_mut().state.tick_finish()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// chaperone
|
// chaperone
|
||||||
|
|||||||
@@ -402,7 +402,7 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
|
|||||||
|
|
||||||
#[cfg(feature = "wayvr")]
|
#[cfg(feature = "wayvr")]
|
||||||
if let Some(wayvr) = &app_state.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()?;
|
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)
|
.map(PathBuf::from)
|
||||||
.unwrap_or_else(|_| PathBuf::from("/tmp"));
|
.unwrap_or_else(|_| PathBuf::from("/tmp"));
|
||||||
path.push("wayvr.disp");
|
path.push("wayvr.disp");
|
||||||
std::fs::write(path, format!("{}\n", display_num)).unwrap();
|
std::fs::write(path, format!("{}\n", display_num))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ use crate::{backend::overlay::OverlayID, gen_id};
|
|||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
client::WayVRManager, comp::send_frames_surface_tree, egl_data, event_queue::SyncEventQueue,
|
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 {
|
fn generate_auth_key() -> String {
|
||||||
@@ -54,6 +54,7 @@ pub struct Display {
|
|||||||
wm: Rc<RefCell<window::WindowManager>>,
|
wm: Rc<RefCell<window::WindowManager>>,
|
||||||
pub displayed_windows: Vec<DisplayWindow>,
|
pub displayed_windows: Vec<DisplayWindow>,
|
||||||
wayland_env: super::WaylandEnv,
|
wayland_env: super::WaylandEnv,
|
||||||
|
last_pressed_time_ms: u64,
|
||||||
|
|
||||||
// Render data stuff
|
// Render data stuff
|
||||||
gles_texture: GlesTexture, // TODO: drop texture
|
gles_texture: GlesTexture, // TODO: drop texture
|
||||||
@@ -121,6 +122,7 @@ impl Display {
|
|||||||
primary,
|
primary,
|
||||||
overlay_id: None,
|
overlay_id: None,
|
||||||
tasks: SyncEventQueue::new(),
|
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) {
|
if let Some(window_handle) = self.get_hovered_window(x, y) {
|
||||||
let wm = self.wm.borrow();
|
let wm = self.wm.borrow();
|
||||||
if let Some(window) = wm.windows.get(&window_handle) {
|
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
|
// Change keyboard focus to pressed window
|
||||||
let loc = manager.seat_pointer.current_location();
|
let loc = manager.seat_pointer.current_location();
|
||||||
|
|
||||||
|
self.last_pressed_time_ms = time::get_millis();
|
||||||
|
|
||||||
if let Some(window_handle) =
|
if let Some(window_handle) =
|
||||||
self.get_hovered_window(loc.x.max(0.0) as u32, loc.y.max(0.0) as u32)
|
self.get_hovered_window(loc.x.max(0.0) as u32, loc.y.max(0.0) as u32)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ macro_rules! gen_id {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//ThingHandle
|
//ThingHandle
|
||||||
#[derive(Default, Clone, Copy, PartialEq)]
|
#[derive(Default, Clone, Copy, PartialEq, Hash, Eq)]
|
||||||
pub struct $handle_name {
|
pub struct $handle_name {
|
||||||
idx: u32,
|
idx: u32,
|
||||||
generation: u64,
|
generation: u64,
|
||||||
|
|||||||
@@ -65,6 +65,12 @@ pub enum WayVRTask {
|
|||||||
ProcessTerminationRequest(process::ProcessHandle),
|
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)]
|
#[allow(dead_code)]
|
||||||
pub struct WayVR {
|
pub struct WayVR {
|
||||||
time_start: u64,
|
time_start: u64,
|
||||||
@@ -74,6 +80,7 @@ pub struct WayVR {
|
|||||||
wm: Rc<RefCell<window::WindowManager>>,
|
wm: Rc<RefCell<window::WindowManager>>,
|
||||||
egl_data: Rc<egl_data::EGLData>,
|
egl_data: Rc<egl_data::EGLData>,
|
||||||
pub processes: process::ProcessVec,
|
pub processes: process::ProcessVec,
|
||||||
|
config: Config,
|
||||||
|
|
||||||
tasks: SyncEventQueue<WayVRTask>,
|
tasks: SyncEventQueue<WayVRTask>,
|
||||||
}
|
}
|
||||||
@@ -89,7 +96,7 @@ pub enum TickResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl WayVR {
|
impl WayVR {
|
||||||
pub fn new() -> anyhow::Result<Self> {
|
pub fn new(config: Config) -> anyhow::Result<Self> {
|
||||||
log::info!("Initializing WayVR");
|
log::info!("Initializing WayVR");
|
||||||
let display: wayland_server::Display<Application> = wayland_server::Display::new()?;
|
let display: wayland_server::Display<Application> = wayland_server::Display::new()?;
|
||||||
let dh = display.handle();
|
let dh = display.handle();
|
||||||
@@ -100,8 +107,11 @@ impl WayVR {
|
|||||||
let data_device = DataDeviceState::new::<Application>(&dh);
|
let data_device = DataDeviceState::new::<Application>(&dh);
|
||||||
let mut seat = seat_state.new_wl_seat(&dh, "wayvr");
|
let mut seat = seat_state.new_wl_seat(&dh, "wayvr");
|
||||||
|
|
||||||
// TODO: Keyboard repeat delay and rate?
|
let seat_keyboard = seat.add_keyboard(
|
||||||
let seat_keyboard = seat.add_keyboard(Default::default(), 100, 100)?;
|
Default::default(),
|
||||||
|
config.keyboard_repeat_delay_ms as i32,
|
||||||
|
config.keyboard_repeat_rate as i32,
|
||||||
|
)?;
|
||||||
let seat_pointer = seat.add_pointer();
|
let seat_pointer = seat.add_pointer();
|
||||||
|
|
||||||
let tasks = SyncEventQueue::new();
|
let tasks = SyncEventQueue::new();
|
||||||
@@ -131,6 +141,7 @@ impl WayVR {
|
|||||||
egl_data: Rc::new(egl_data),
|
egl_data: Rc::new(egl_data),
|
||||||
wm: Rc::new(RefCell::new(window::WindowManager::new())),
|
wm: Rc::new(RefCell::new(window::WindowManager::new())),
|
||||||
tasks,
|
tasks,
|
||||||
|
config,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,7 +233,7 @@ impl WayVR {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log::error!(
|
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
|
client.pid
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -255,12 +266,12 @@ impl WayVR {
|
|||||||
|
|
||||||
pub fn send_mouse_move(&mut self, display: display::DisplayHandle, x: u32, y: u32) {
|
pub fn send_mouse_move(&mut self, display: display::DisplayHandle, x: u32, y: u32) {
|
||||||
if let Some(display) = self.displays.get(&display) {
|
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) {
|
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);
|
display.send_mouse_down(&mut self.manager, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ use crate::{
|
|||||||
wayvr,
|
wayvr,
|
||||||
},
|
},
|
||||||
config::{load_known_yaml, ConfigType},
|
config::{load_known_yaml, ConfigType},
|
||||||
overlays::wayvr::WayVRAction,
|
overlays::wayvr::{WayVRAction, WayVRState},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Flat version of RelativeTo
|
// Flat version of RelativeTo
|
||||||
@@ -106,10 +106,19 @@ impl WayVRConfig {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_wayvr_config(config: &crate::config::GeneralConfig) -> wayvr::Config {
|
||||||
|
wayvr::Config {
|
||||||
|
click_freeze_time_ms: config.click_freeze_time_ms,
|
||||||
|
keyboard_repeat_delay_ms: 200,
|
||||||
|
keyboard_repeat_rate: 50,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn post_load(
|
pub fn post_load(
|
||||||
&self,
|
&self,
|
||||||
|
config: &crate::config::GeneralConfig,
|
||||||
tasks: &mut TaskContainer,
|
tasks: &mut TaskContainer,
|
||||||
) -> anyhow::Result<Option<Rc<RefCell<wayvr::WayVR>>>> {
|
) -> anyhow::Result<Option<Rc<RefCell<WayVRState>>>> {
|
||||||
let primary_count = self
|
let primary_count = self
|
||||||
.displays
|
.displays
|
||||||
.iter()
|
.iter()
|
||||||
@@ -137,7 +146,9 @@ impl WayVRConfig {
|
|||||||
|
|
||||||
if self.run_compositor_at_start {
|
if self.run_compositor_at_start {
|
||||||
// Start Wayland server instantly
|
// Start Wayland server instantly
|
||||||
Ok(Some(Rc::new(RefCell::new(wayvr::WayVR::new()?))))
|
Ok(Some(Rc::new(RefCell::new(WayVRState::new(
|
||||||
|
Self::get_wayvr_config(config),
|
||||||
|
)?))))
|
||||||
} else {
|
} else {
|
||||||
// Lazy-init WayVR later if the user requested
|
// Lazy-init WayVR later if the user requested
|
||||||
Ok(None)
|
Ok(None)
|
||||||
|
|||||||
@@ -32,12 +32,6 @@ const AUTO_RELEASE_MODS: [KeyModifier; 5] = [SHIFT, CTRL, ALT, SUPER, META];
|
|||||||
pub const KEYBOARD_NAME: &str = "kbd";
|
pub const KEYBOARD_NAME: &str = "kbd";
|
||||||
|
|
||||||
fn send_key(app: &mut AppState, key: VirtualKey, down: bool) {
|
fn send_key(app: &mut AppState, key: VirtualKey, down: bool) {
|
||||||
log::info!(
|
|
||||||
"Sending key {:?} to {:?} (down: {})",
|
|
||||||
key,
|
|
||||||
app.keyboard_focus,
|
|
||||||
down
|
|
||||||
);
|
|
||||||
match app.keyboard_focus {
|
match app.keyboard_focus {
|
||||||
KeyboardFocus::PhysicalScreen => {
|
KeyboardFocus::PhysicalScreen => {
|
||||||
app.hid_provider.send_key(key, down);
|
app.hid_provider.send_key(key, down);
|
||||||
@@ -46,7 +40,7 @@ fn send_key(app: &mut AppState, key: VirtualKey, down: bool) {
|
|||||||
{
|
{
|
||||||
#[cfg(feature = "wayvr")]
|
#[cfg(feature = "wayvr")]
|
||||||
if let Some(wayvr) = &app.wayvr {
|
if let Some(wayvr) = &app.wayvr {
|
||||||
wayvr.borrow_mut().send_key(key as u32, down);
|
wayvr.borrow_mut().state.send_key(key as u32, down);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -241,7 +235,6 @@ fn key_press(
|
|||||||
|
|
||||||
app.hid_provider.set_modifiers(data.modifiers);
|
app.hid_provider.set_modifiers(data.modifiers);
|
||||||
|
|
||||||
|
|
||||||
send_key(app, *vk, true);
|
send_key(app, *vk, true);
|
||||||
*pressed = true;
|
*pressed = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use glam::{vec3a, Affine2, Vec3, Vec3A};
|
use glam::{vec3a, Affine2, Vec3, Vec3A};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::{cell::RefCell, rc::Rc, sync::Arc};
|
use std::{cell::RefCell, collections::HashMap, rc::Rc, sync::Arc};
|
||||||
use vulkano::image::SubresourceLayout;
|
use vulkano::image::SubresourceLayout;
|
||||||
use wlx_capture::frame::{DmabufFrame, FourCC, FrameFormat, FramePlane};
|
use wlx_capture::frame::{DmabufFrame, FourCC, FrameFormat, FramePlane};
|
||||||
|
|
||||||
@@ -8,7 +8,10 @@ use crate::{
|
|||||||
backend::{
|
backend::{
|
||||||
common::OverlayContainer,
|
common::OverlayContainer,
|
||||||
input::{self, InteractionHandler},
|
input::{self, InteractionHandler},
|
||||||
overlay::{ui_transform, OverlayData, OverlayRenderer, OverlayState, SplitOverlayBackend},
|
overlay::{
|
||||||
|
ui_transform, OverlayData, OverlayID, OverlayRenderer, OverlayState,
|
||||||
|
SplitOverlayBackend,
|
||||||
|
},
|
||||||
wayvr::{self, display, WayVR},
|
wayvr::{self, display, WayVR},
|
||||||
},
|
},
|
||||||
graphics::WlxGraphics,
|
graphics::WlxGraphics,
|
||||||
@@ -16,13 +19,13 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub struct WayVRContext {
|
pub struct WayVRContext {
|
||||||
wayvr: Rc<RefCell<wayvr::WayVR>>,
|
wayvr: Rc<RefCell<WayVRState>>,
|
||||||
display: wayvr::display::DisplayHandle,
|
display: wayvr::display::DisplayHandle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WayVRContext {
|
impl WayVRContext {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
wvr: Rc<RefCell<wayvr::WayVR>>,
|
wvr: Rc<RefCell<WayVRState>>,
|
||||||
display: wayvr::display::DisplayHandle,
|
display: wayvr::display::DisplayHandle,
|
||||||
) -> anyhow::Result<Self> {
|
) -> anyhow::Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
@@ -32,6 +35,20 @@ impl WayVRContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct WayVRState {
|
||||||
|
pub display_handle_map: HashMap<display::DisplayHandle, OverlayID>,
|
||||||
|
pub state: WayVR,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WayVRState {
|
||||||
|
pub fn new(config: wayvr::Config) -> anyhow::Result<Self> {
|
||||||
|
Ok(Self {
|
||||||
|
display_handle_map: Default::default(),
|
||||||
|
state: WayVR::new(config)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct WayVRInteractionHandler {
|
pub struct WayVRInteractionHandler {
|
||||||
context: Rc<RefCell<WayVRContext>>,
|
context: Rc<RefCell<WayVRContext>>,
|
||||||
mouse_transform: Affine2,
|
mouse_transform: Affine2,
|
||||||
@@ -54,7 +71,7 @@ impl InteractionHandler for WayVRInteractionHandler {
|
|||||||
) -> Option<input::Haptics> {
|
) -> Option<input::Haptics> {
|
||||||
let ctx = self.context.borrow();
|
let ctx = self.context.borrow();
|
||||||
|
|
||||||
let mut wayvr = ctx.wayvr.borrow_mut();
|
let wayvr = &mut ctx.wayvr.borrow_mut().state;
|
||||||
if let Some(disp) = wayvr.displays.get(&ctx.display) {
|
if let Some(disp) = wayvr.displays.get(&ctx.display) {
|
||||||
let pos = self.mouse_transform.transform_point2(hit.uv);
|
let pos = self.mouse_transform.transform_point2(hit.uv);
|
||||||
let x = ((pos.x * disp.width as f32) as i32).max(0);
|
let x = ((pos.x * disp.width as f32) as i32).max(0);
|
||||||
@@ -82,7 +99,7 @@ impl InteractionHandler for WayVRInteractionHandler {
|
|||||||
}
|
}
|
||||||
} {
|
} {
|
||||||
let ctx = self.context.borrow();
|
let ctx = self.context.borrow();
|
||||||
let mut wayvr = ctx.wayvr.borrow_mut();
|
let wayvr = &mut ctx.wayvr.borrow_mut().state;
|
||||||
if pressed {
|
if pressed {
|
||||||
wayvr.send_mouse_down(ctx.display, index);
|
wayvr.send_mouse_down(ctx.display, index);
|
||||||
} else {
|
} else {
|
||||||
@@ -93,7 +110,10 @@ impl InteractionHandler for WayVRInteractionHandler {
|
|||||||
|
|
||||||
fn on_scroll(&mut self, _app: &mut state::AppState, _hit: &input::PointerHit, delta: f32) {
|
fn on_scroll(&mut self, _app: &mut state::AppState, _hit: &input::PointerHit, delta: f32) {
|
||||||
let ctx = self.context.borrow();
|
let ctx = self.context.borrow();
|
||||||
ctx.wayvr.borrow_mut().send_mouse_scroll(ctx.display, delta);
|
ctx.wayvr
|
||||||
|
.borrow_mut()
|
||||||
|
.state
|
||||||
|
.send_mouse_scroll(ctx.display, delta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +127,7 @@ pub struct WayVRRenderer {
|
|||||||
impl WayVRRenderer {
|
impl WayVRRenderer {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
app: &mut state::AppState,
|
app: &mut state::AppState,
|
||||||
wvr: Rc<RefCell<wayvr::WayVR>>,
|
wvr: Rc<RefCell<WayVRState>>,
|
||||||
display: wayvr::display::DisplayHandle,
|
display: wayvr::display::DisplayHandle,
|
||||||
) -> anyhow::Result<Self> {
|
) -> anyhow::Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
@@ -121,7 +141,7 @@ impl WayVRRenderer {
|
|||||||
|
|
||||||
fn get_or_create_display<O>(
|
fn get_or_create_display<O>(
|
||||||
app: &mut AppState,
|
app: &mut AppState,
|
||||||
wayvr: &mut WayVR,
|
wayvr: &mut WayVRState,
|
||||||
disp_name: &str,
|
disp_name: &str,
|
||||||
) -> anyhow::Result<(display::DisplayHandle, Option<OverlayData<O>>)>
|
) -> anyhow::Result<(display::DisplayHandle, Option<OverlayData<O>>)>
|
||||||
where
|
where
|
||||||
@@ -129,7 +149,8 @@ where
|
|||||||
{
|
{
|
||||||
let created_overlay: Option<OverlayData<O>>;
|
let created_overlay: Option<OverlayData<O>>;
|
||||||
|
|
||||||
let disp_handle = if let Some(disp) = WayVR::get_display_by_name(&wayvr.displays, disp_name) {
|
let disp_handle =
|
||||||
|
if let Some(disp) = WayVR::get_display_by_name(&wayvr.state.displays, disp_name) {
|
||||||
created_overlay = None;
|
created_overlay = None;
|
||||||
disp
|
disp
|
||||||
} else {
|
} else {
|
||||||
@@ -143,7 +164,7 @@ where
|
|||||||
))?
|
))?
|
||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
let disp_handle = wayvr.create_display(
|
let disp_handle = wayvr.state.create_display(
|
||||||
conf_display.width,
|
conf_display.width,
|
||||||
conf_display.height,
|
conf_display.height,
|
||||||
disp_name,
|
disp_name,
|
||||||
@@ -158,6 +179,10 @@ where
|
|||||||
conf_display.scale.unwrap_or(1.0),
|
conf_display.scale.unwrap_or(1.0),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
wayvr
|
||||||
|
.display_handle_map
|
||||||
|
.insert(disp_handle, overlay.state.id);
|
||||||
|
|
||||||
if let Some(attach_to) = &conf_display.attach_to {
|
if let Some(attach_to) = &conf_display.attach_to {
|
||||||
overlay.state.relative_to = attach_to.get_relative_to();
|
overlay.state.relative_to = attach_to.get_relative_to();
|
||||||
}
|
}
|
||||||
@@ -173,7 +198,7 @@ where
|
|||||||
overlay.state.spawn_point = Vec3A::from_slice(pos);
|
overlay.state.spawn_point = Vec3A::from_slice(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
let display = wayvr.displays.get_mut(&disp_handle).unwrap(); // Never fails
|
let display = wayvr.state.displays.get_mut(&disp_handle).unwrap(); // Never fails
|
||||||
display.overlay_id = Some(overlay.state.id);
|
display.overlay_id = Some(overlay.state.id);
|
||||||
|
|
||||||
created_overlay = Some(overlay);
|
created_overlay = Some(overlay);
|
||||||
@@ -189,7 +214,7 @@ where
|
|||||||
O: Default,
|
O: Default,
|
||||||
{
|
{
|
||||||
if let Some(wayvr) = app.wayvr.clone() {
|
if let Some(wayvr) = app.wayvr.clone() {
|
||||||
let res = wayvr.borrow_mut().tick_events()?;
|
let res = wayvr.borrow_mut().state.tick_events()?;
|
||||||
|
|
||||||
for result in res {
|
for result in res {
|
||||||
match result {
|
match result {
|
||||||
@@ -214,9 +239,9 @@ where
|
|||||||
let (disp_handle, created_overlay) =
|
let (disp_handle, created_overlay) =
|
||||||
get_or_create_display::<O>(app, &mut wayvr, &disp_name)?;
|
get_or_create_display::<O>(app, &mut wayvr, &disp_name)?;
|
||||||
|
|
||||||
wayvr.add_external_process(disp_handle, req.pid);
|
wayvr.state.add_external_process(disp_handle, req.pid);
|
||||||
|
|
||||||
wayvr.manager.add_client(wayvr::client::WayVRClient {
|
wayvr.state.manager.add_client(wayvr::client::WayVRClient {
|
||||||
client: req.client,
|
client: req.client,
|
||||||
display_handle: disp_handle,
|
display_handle: disp_handle,
|
||||||
pid: req.pid,
|
pid: req.pid,
|
||||||
@@ -245,7 +270,7 @@ impl WayVRRenderer {
|
|||||||
|
|
||||||
let ctx = self.context.borrow_mut();
|
let ctx = self.context.borrow_mut();
|
||||||
let wayvr = ctx.wayvr.borrow_mut();
|
let wayvr = ctx.wayvr.borrow_mut();
|
||||||
if let Some(disp) = wayvr.displays.get(&ctx.display) {
|
if let Some(disp) = wayvr.state.displays.get(&ctx.display) {
|
||||||
let frame = DmabufFrame {
|
let frame = DmabufFrame {
|
||||||
format: FrameFormat {
|
format: FrameFormat {
|
||||||
width: disp.width,
|
width: disp.width,
|
||||||
@@ -293,14 +318,14 @@ impl OverlayRenderer for WayVRRenderer {
|
|||||||
|
|
||||||
fn pause(&mut self, _app: &mut state::AppState) -> anyhow::Result<()> {
|
fn pause(&mut self, _app: &mut state::AppState) -> anyhow::Result<()> {
|
||||||
let ctx = self.context.borrow_mut();
|
let ctx = self.context.borrow_mut();
|
||||||
let mut wayvr = ctx.wayvr.borrow_mut();
|
let wayvr = &mut ctx.wayvr.borrow_mut().state;
|
||||||
wayvr.set_display_visible(ctx.display, false);
|
wayvr.set_display_visible(ctx.display, false);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resume(&mut self, _app: &mut state::AppState) -> anyhow::Result<()> {
|
fn resume(&mut self, _app: &mut state::AppState) -> anyhow::Result<()> {
|
||||||
let ctx = self.context.borrow_mut();
|
let ctx = self.context.borrow_mut();
|
||||||
let mut wayvr = ctx.wayvr.borrow_mut();
|
let wayvr = &mut ctx.wayvr.borrow_mut().state;
|
||||||
wayvr.set_display_visible(ctx.display, true);
|
wayvr.set_display_visible(ctx.display, true);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -309,9 +334,10 @@ impl OverlayRenderer for WayVRRenderer {
|
|||||||
let ctx = self.context.borrow();
|
let ctx = self.context.borrow();
|
||||||
let mut wayvr = ctx.wayvr.borrow_mut();
|
let mut wayvr = ctx.wayvr.borrow_mut();
|
||||||
|
|
||||||
wayvr.tick_display(ctx.display)?;
|
wayvr.state.tick_display(ctx.display)?;
|
||||||
|
|
||||||
let dmabuf_data = wayvr
|
let dmabuf_data = wayvr
|
||||||
|
.state
|
||||||
.get_dmabuf_data(ctx.display)
|
.get_dmabuf_data(ctx.display)
|
||||||
.ok_or(anyhow::anyhow!("Failed to fetch dmabuf data"))?
|
.ok_or(anyhow::anyhow!("Failed to fetch dmabuf data"))?
|
||||||
.clone();
|
.clone();
|
||||||
@@ -392,8 +418,24 @@ pub enum WayVRAction {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn show_display<O>(wayvr: &mut WayVRState, overlays: &mut OverlayContainer<O>, display_name: &str)
|
||||||
|
where
|
||||||
|
O: Default,
|
||||||
|
{
|
||||||
|
if let Some(display) = WayVR::get_display_by_name(&wayvr.state.displays, display_name) {
|
||||||
|
if let Some(overlay_id) = wayvr.display_handle_map.get(&display) {
|
||||||
|
if let Some(overlay) = overlays.mut_by_id(*overlay_id) {
|
||||||
|
overlay.state.want_visible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wayvr.state.set_display_visible(display, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn action_app_click<O>(
|
fn action_app_click<O>(
|
||||||
app: &mut AppState,
|
app: &mut AppState,
|
||||||
|
overlays: &mut OverlayContainer<O>,
|
||||||
catalog_name: &Arc<str>,
|
catalog_name: &Arc<str>,
|
||||||
app_name: &Arc<str>,
|
app_name: &Arc<str>,
|
||||||
) -> anyhow::Result<Option<OverlayData<O>>>
|
) -> anyhow::Result<Option<OverlayData<O>>>
|
||||||
@@ -437,13 +479,19 @@ where
|
|||||||
|
|
||||||
// Terminate existing process if required
|
// Terminate existing process if required
|
||||||
if let Some(process_handle) =
|
if let Some(process_handle) =
|
||||||
wayvr.process_query(disp_handle, &app_entry.exec, &args_vec, &env_vec)
|
wayvr
|
||||||
|
.state
|
||||||
|
.process_query(disp_handle, &app_entry.exec, &args_vec, &env_vec)
|
||||||
{
|
{
|
||||||
// Terminate process
|
// Terminate process
|
||||||
wayvr.terminate_process(process_handle);
|
wayvr.state.terminate_process(process_handle);
|
||||||
} else {
|
} else {
|
||||||
// Spawn process
|
// Spawn process
|
||||||
wayvr.spawn_process(disp_handle, &app_entry.exec, &args_vec, &env_vec)?;
|
wayvr
|
||||||
|
.state
|
||||||
|
.spawn_process(disp_handle, &app_entry.exec, &args_vec, &env_vec)?;
|
||||||
|
|
||||||
|
show_display(&mut wayvr, overlays, &app_entry.target_display.as_str());
|
||||||
}
|
}
|
||||||
Ok(created_overlay)
|
Ok(created_overlay)
|
||||||
} else {
|
} else {
|
||||||
@@ -463,8 +511,8 @@ where
|
|||||||
let wayvr = app.get_wayvr()?;
|
let wayvr = app.get_wayvr()?;
|
||||||
let mut wayvr = wayvr.borrow_mut();
|
let mut wayvr = wayvr.borrow_mut();
|
||||||
|
|
||||||
if let Some(handle) = WayVR::get_display_by_name(&wayvr.displays, display_name) {
|
if let Some(handle) = WayVR::get_display_by_name(&wayvr.state.displays, display_name) {
|
||||||
if let Some(display) = wayvr.displays.get_mut(&handle) {
|
if let Some(display) = wayvr.state.displays.get_mut(&handle) {
|
||||||
if let Some(overlay_id) = display.overlay_id {
|
if let Some(overlay_id) = display.overlay_id {
|
||||||
if let Some(overlay) = overlays.mut_by_id(overlay_id) {
|
if let Some(overlay) = overlays.mut_by_id(overlay_id) {
|
||||||
match action {
|
match action {
|
||||||
@@ -495,7 +543,7 @@ where
|
|||||||
catalog_name,
|
catalog_name,
|
||||||
app_name,
|
app_name,
|
||||||
} => {
|
} => {
|
||||||
match action_app_click(app, catalog_name, app_name) {
|
match action_app_click(app, overlays, catalog_name, app_name) {
|
||||||
Ok(res) => {
|
Ok(res) => {
|
||||||
if let Some(created_overlay) = res {
|
if let Some(created_overlay) = res {
|
||||||
overlays.add(created_overlay);
|
overlays.add(created_overlay);
|
||||||
|
|||||||
24
src/state.rs
24
src/state.rs
@@ -8,13 +8,11 @@ use std::{io::Cursor, sync::Arc};
|
|||||||
use vulkano::image::view::ImageView;
|
use vulkano::image::view::ImageView;
|
||||||
|
|
||||||
#[cfg(feature = "wayvr")]
|
#[cfg(feature = "wayvr")]
|
||||||
use std::{cell::RefCell, rc::Rc};
|
use {
|
||||||
|
crate::config_wayvr::{self, WayVRConfig},
|
||||||
#[cfg(feature = "wayvr")]
|
crate::overlays::wayvr::WayVRState,
|
||||||
use crate::backend::wayvr::WayVR;
|
std::{cell::RefCell, rc::Rc},
|
||||||
|
};
|
||||||
#[cfg(feature = "wayvr")]
|
|
||||||
use crate::config_wayvr::{self, WayVRConfig};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{input::InputState, overlay::OverlayID, task::TaskContainer},
|
backend::{input::InputState, overlay::OverlayID, task::TaskContainer},
|
||||||
@@ -52,7 +50,7 @@ pub struct AppState {
|
|||||||
pub keyboard_focus: KeyboardFocus,
|
pub keyboard_focus: KeyboardFocus,
|
||||||
|
|
||||||
#[cfg(feature = "wayvr")]
|
#[cfg(feature = "wayvr")]
|
||||||
pub wayvr: Option<Rc<RefCell<WayVR>>>, // Dynamically created if requested
|
pub wayvr: Option<Rc<RefCell<WayVRState>>>, // Dynamically created if requested
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppState {
|
impl AppState {
|
||||||
@@ -100,7 +98,9 @@ impl AppState {
|
|||||||
let session = AppSession::load();
|
let session = AppSession::load();
|
||||||
|
|
||||||
#[cfg(feature = "wayvr")]
|
#[cfg(feature = "wayvr")]
|
||||||
let wayvr = session.wayvr_config.post_load(&mut tasks)?;
|
let wayvr = session
|
||||||
|
.wayvr_config
|
||||||
|
.post_load(&session.config, &mut tasks)?;
|
||||||
|
|
||||||
Ok(AppState {
|
Ok(AppState {
|
||||||
fc: FontCache::new(session.config.primary_font.clone())?,
|
fc: FontCache::new(session.config.primary_font.clone())?,
|
||||||
@@ -122,11 +122,13 @@ impl AppState {
|
|||||||
|
|
||||||
#[cfg(feature = "wayvr")]
|
#[cfg(feature = "wayvr")]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn get_wayvr(&mut self) -> anyhow::Result<Rc<RefCell<WayVR>>> {
|
pub fn get_wayvr(&mut self) -> anyhow::Result<Rc<RefCell<WayVRState>>> {
|
||||||
if let Some(wvr) = &self.wayvr {
|
if let Some(wvr) = &self.wayvr {
|
||||||
Ok(wvr.clone())
|
Ok(wvr.clone())
|
||||||
} else {
|
} else {
|
||||||
let wayvr = Rc::new(RefCell::new(WayVR::new()?));
|
let wayvr = Rc::new(RefCell::new(WayVRState::new(
|
||||||
|
WayVRConfig::get_wayvr_config(&self.session.config),
|
||||||
|
)?));
|
||||||
self.wayvr = Some(wayvr.clone());
|
self.wayvr = Some(wayvr.clone());
|
||||||
Ok(wayvr)
|
Ok(wayvr)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user