WayVR: Display auto-hide support (Fixes #98), keyboard settings in config

This commit is contained in:
Aleksander
2024-11-05 16:20:38 +01:00
committed by galister
parent d212098a98
commit 502cf5d372
6 changed files with 117 additions and 16 deletions

View File

@@ -15,11 +15,14 @@ use smithay::{
wayland::shell::xdg::ToplevelSurface, wayland::shell::xdg::ToplevelSurface,
}; };
use crate::{backend::overlay::OverlayID, gen_id}; use crate::{
backend::{overlay::OverlayID, wayvr::time::get_millis},
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, time, window, process, smithay_wrapper, time, window, WayVRSignal,
}; };
fn generate_auth_key() -> String { fn generate_auth_key() -> String {
@@ -55,6 +58,7 @@ pub struct Display {
pub displayed_windows: Vec<DisplayWindow>, pub displayed_windows: Vec<DisplayWindow>,
wayland_env: super::WaylandEnv, wayland_env: super::WaylandEnv,
last_pressed_time_ms: u64, last_pressed_time_ms: u64,
pub no_windows_since: Option<u64>,
// Render data stuff // Render data stuff
gles_texture: GlesTexture, // TODO: drop texture gles_texture: GlesTexture, // TODO: drop texture
@@ -123,6 +127,7 @@ impl Display {
overlay_id: None, overlay_id: None,
tasks: SyncEventQueue::new(), tasks: SyncEventQueue::new(),
last_pressed_time_ms: 0, last_pressed_time_ms: 0,
no_windows_since: None,
}) })
} }
@@ -158,7 +163,24 @@ impl Display {
} }
} }
pub fn tick(&mut self) { pub fn tick(
&mut self,
config: &super::Config,
handle: &DisplayHandle,
signals: &mut SyncEventQueue<WayVRSignal>,
) {
if self.visible {
if !self.displayed_windows.is_empty() {
self.no_windows_since = None;
} else if let Some(auto_hide_delay) = config.auto_hide_delay {
if let Some(s) = self.no_windows_since {
if s + (auto_hide_delay as u64) < get_millis() {
signals.send(WayVRSignal::DisplayHideRequest(*handle));
}
}
}
}
while let Some(task) = self.tasks.read() { while let Some(task) = self.tasks.read() {
match task { match task {
DisplayTask::ProcessCleanup(process_handle) => { DisplayTask::ProcessCleanup(process_handle) => {
@@ -169,6 +191,7 @@ impl Display {
self.name, self.name,
self.displayed_windows.len() self.displayed_windows.len()
); );
self.no_windows_since = Some(get_millis());
self.reposition_windows(); self.reposition_windows();
} }
@@ -248,6 +271,7 @@ impl Display {
self.visible = visible; self.visible = visible;
if visible { if visible {
self.wants_redraw = true; self.wants_redraw = true;
self.no_windows_since = None;
} }
} }
} }

View File

@@ -65,10 +65,16 @@ pub enum WayVRTask {
ProcessTerminationRequest(process::ProcessHandle), ProcessTerminationRequest(process::ProcessHandle),
} }
#[derive(Clone)]
pub enum WayVRSignal {
DisplayHideRequest(display::DisplayHandle),
}
pub struct Config { pub struct Config {
pub click_freeze_time_ms: u32, pub click_freeze_time_ms: u32,
pub keyboard_repeat_delay_ms: u32, pub keyboard_repeat_delay_ms: u32,
pub keyboard_repeat_rate: u32, pub keyboard_repeat_rate: u32,
pub auto_hide_delay: Option<u32>, // if None, auto-hide is disabled
} }
#[allow(dead_code)] #[allow(dead_code)]
@@ -83,6 +89,7 @@ pub struct WayVR {
config: Config, config: Config,
tasks: SyncEventQueue<WayVRTask>, tasks: SyncEventQueue<WayVRTask>,
pub signals: SyncEventQueue<WayVRSignal>,
} }
pub enum MouseIndex { pub enum MouseIndex {
@@ -140,6 +147,7 @@ impl WayVR {
processes: ProcessVec::new(), processes: ProcessVec::new(),
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())),
signals: SyncEventQueue::new(),
tasks, tasks,
config, config,
}) })
@@ -206,9 +214,9 @@ impl WayVR {
} }
} }
for display in self.displays.vec.iter_mut().flatten() { self.displays.iter_mut(&mut |handle, display| {
display.obj.tick(); display.tick(&self.config, &handle, &mut self.signals);
} });
while let Some(task) = self.tasks.read() { while let Some(task) = self.tasks.read() {
match task { match task {

View File

@@ -80,12 +80,40 @@ impl WayVRCatalog {
} }
} }
fn def_true() -> bool {
true
}
fn def_autohide_delay() -> u32 {
750
}
fn def_keyboard_repeat_delay() -> u32 {
200
}
fn def_keyboard_repeat_rate() -> u32 {
50
}
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
pub struct WayVRConfig { pub struct WayVRConfig {
pub version: u32, pub version: u32,
pub run_compositor_at_start: bool, pub run_compositor_at_start: bool,
pub catalogs: HashMap<String, WayVRCatalog>, pub catalogs: HashMap<String, WayVRCatalog>,
pub displays: BTreeMap<String, WayVRDisplay>, // sorted alphabetically pub displays: BTreeMap<String, WayVRDisplay>, // sorted alphabetically
#[serde(default = "def_true")]
pub auto_hide: bool,
#[serde(default = "def_autohide_delay")]
pub auto_hide_delay: u32,
#[serde(default = "def_keyboard_repeat_delay")]
pub keyboard_repeat_delay: u32,
#[serde(default = "def_keyboard_repeat_rate")]
pub keyboard_repeat_rate: u32,
} }
impl WayVRConfig { impl WayVRConfig {
@@ -106,11 +134,19 @@ impl WayVRConfig {
None None
} }
pub fn get_wayvr_config(config: &crate::config::GeneralConfig) -> wayvr::Config { pub fn get_wayvr_config(
config_general: &crate::config::GeneralConfig,
config_wayvr: &crate::config_wayvr::WayVRConfig,
) -> wayvr::Config {
wayvr::Config { wayvr::Config {
click_freeze_time_ms: config.click_freeze_time_ms, click_freeze_time_ms: config_general.click_freeze_time_ms,
keyboard_repeat_delay_ms: 200, keyboard_repeat_delay_ms: config_wayvr.keyboard_repeat_delay,
keyboard_repeat_rate: 50, keyboard_repeat_rate: config_wayvr.keyboard_repeat_rate,
auto_hide_delay: if config_wayvr.auto_hide {
Some(config_wayvr.auto_hide_delay)
} else {
None
},
} }
} }
@@ -147,7 +183,7 @@ 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(WayVRState::new( Ok(Some(Rc::new(RefCell::new(WayVRState::new(
Self::get_wayvr_config(config), Self::get_wayvr_config(config, &self),
)?)))) )?))))
} else { } else {
// Lazy-init WayVR later if the user requested // Lazy-init WayVR later if the user requested

View File

@@ -6,12 +6,13 @@ use wlx_capture::frame::{DmabufFrame, FourCC, FrameFormat, FramePlane};
use crate::{ use crate::{
backend::{ backend::{
common::OverlayContainer, common::{OverlayContainer, OverlaySelector},
input::{self, InteractionHandler}, input::{self, InteractionHandler},
overlay::{ overlay::{
ui_transform, OverlayData, OverlayID, OverlayRenderer, OverlayState, ui_transform, OverlayData, OverlayID, OverlayRenderer, OverlayState,
SplitOverlayBackend, SplitOverlayBackend,
}, },
task::TaskType,
wayvr::{self, display, WayVR}, wayvr::{self, display, WayVR},
}, },
graphics::WlxGraphics, graphics::WlxGraphics,
@@ -213,8 +214,27 @@ pub fn tick_events<O>(app: &mut AppState, overlays: &mut OverlayContainer<O>) ->
where where
O: Default, O: Default,
{ {
if let Some(wayvr) = app.wayvr.clone() { if let Some(r_wayvr) = app.wayvr.clone() {
let res = wayvr.borrow_mut().state.tick_events()?; let mut wayvr = r_wayvr.borrow_mut();
while let Some(signal) = wayvr.state.signals.read() {
match signal {
wayvr::WayVRSignal::DisplayHideRequest(display_handle) => {
if let Some(overlay_id) = wayvr.display_handle_map.get(&display_handle) {
let overlay_id = *overlay_id;
wayvr.state.set_display_visible(display_handle, false);
app.tasks.enqueue(TaskType::Overlay(
OverlaySelector::Id(overlay_id),
Box::new(move |_app, o| {
o.want_visible = false;
}),
));
}
}
}
}
let res = wayvr.state.tick_events()?;
drop(wayvr);
for result in res { for result in res {
match result { match result {
@@ -232,7 +252,7 @@ where
}; };
if let Some(disp_name) = disp_name { if let Some(disp_name) = disp_name {
let mut wayvr = wayvr.borrow_mut(); let mut wayvr = r_wayvr.borrow_mut();
log::info!("Registering external process with PID {}", req.pid); log::info!("Registering external process with PID {}", req.pid);

View File

@@ -9,6 +9,19 @@ version: 1
# (used for remote starting external processes) # (used for remote starting external processes)
run_compositor_at_start: false run_compositor_at_start: false
# Automatically close overlays with zero window count?
auto_hide: true
# For how long an overlay should be visible in case if there are no windows present? (in milliseconds, auto_hide needs to be enabled)
# This value shouldn't be set at 0, because some programs could re-initialize a window during startup (splash screens for example)
auto_hide_delay: 750
# In milliseconds
keyboard_repeat_delay: 200
# Chars per second
keyboard_repeat_rate: 50
displays: displays:
Watch: Watch:
width: 400 width: 400

View File

@@ -127,7 +127,7 @@ impl AppState {
Ok(wvr.clone()) Ok(wvr.clone())
} else { } else {
let wayvr = Rc::new(RefCell::new(WayVRState::new( let wayvr = Rc::new(RefCell::new(WayVRState::new(
WayVRConfig::get_wayvr_config(&self.session.config), WayVRConfig::get_wayvr_config(&self.session.config, &self.session.wayvr_config),
)?)); )?));
self.wayvr = Some(wayvr.clone()); self.wayvr = Some(wayvr.clone());
Ok(wayvr) Ok(wayvr)