mirror of
https://github.com/wayvr-org/wayvr.git
synced 2026-10-28 19:04:51 +01:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
89eb2e04f5 | ||
|
|
12253a5e20 | ||
|
|
9e116988ac | ||
|
|
466960d32a |
No files matched your search
@@ -22,7 +22,7 @@ sudo apt-get update
|
||||
sudo apt-get install -y fuse cmake pkg-config fontconfig libasound2-dev libxkbcommon-dev libxkbcommon-x11-0 libxkbcommon-x11-dev \
|
||||
libopenxr-dev libfontconfig-dev libdbus-1-dev libpipewire-0.3-0 libpipewire-0.3-dev libspa-0.2-dev libx11-6 libxext6 libxrandr2 \
|
||||
libx11-dev libxext-dev libxrandr-dev libopenvr-dev libopenvr-api1t64 libwayland-dev libegl-dev libxcb-glx0 libxcb-glx0-dev \
|
||||
dav1d libdav1d-dev libvulkan-dev glslc vulkan-tools libudev-dev libudev1 libinput-dev libinput10
|
||||
dav1d libdav1d-dev libvulkan-dev glslc vulkan-tools libudev-dev libudev1 libinput-dev libinput10 spirv-headers
|
||||
|
||||
rustup update
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
# Contributing
|
||||
|
||||
Contributions are warmly welcome. Before you start, please read the entire document carefully.
|
||||
|
||||
## AI Policy
|
||||
|
||||
Do not use LLMs to generate substantial pieces of code. You need to fully understand every line of code you change. No exceptions.
|
||||
|
||||
Commits, issues and pull requests must be made by humans. Co-authoring by AI is not allowed.
|
||||
Looking to create an issue on the project, such as a feature request or bug report? Focus on writing what you know for sure in simple terms. We'll figure it out from there.
|
||||
|
||||
Usage of Gen-AI for visuals and audio is prohibited.
|
||||
|
||||
The only exception is LLM-translated strings generated by the scripts/translator tool.
|
||||
|
||||
## Basics
|
||||
|
||||
Before committing, make sure to format your Rust code by running:
|
||||
|
||||
```
|
||||
cargo fmt
|
||||
```
|
||||
|
||||
You should also check for any compiler warnings too:
|
||||
|
||||
```
|
||||
cargo check
|
||||
```
|
||||
|
||||
or even better:
|
||||
|
||||
```
|
||||
cargo clippy
|
||||
```
|
||||
|
||||
## Large contributions
|
||||
|
||||
If you want to submit a relatively big pull requests, it's highly advisable to create a separate issue request for it. That way we can discuss the approach and sort out the details first.
|
||||
|
||||
## Adding translations
|
||||
|
||||
Look at `scripts/translator/run.sh` for more information.
|
||||
|
||||
## Licensing
|
||||
|
||||
WayVR is developed and published under [GPL-3 License](https://www.gnu.org/licenses/gpl-3.0.en.html).
|
||||
Generated
+2
-4
@@ -6374,8 +6374,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "whisper-rs"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2088172d00f936c348d6a72f488dc2660ab3f507263a195df308a3c2383229f6"
|
||||
source = "git+https://github.com/wayvr-org/whisper-rs.git?rev=2d908ec36cd41521a28f7f5fb5dc95499fd40051#2d908ec36cd41521a28f7f5fb5dc95499fd40051"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"whisper-rs-sys",
|
||||
@@ -6384,8 +6383,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "whisper-rs-sys"
|
||||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6986c0fe081241d391f09b9a071fbcbb59720c3563628c3c829057cf69f2a56f"
|
||||
source = "git+https://github.com/wayvr-org/whisper-rs.git?rev=2d908ec36cd41521a28f7f5fb5dc95499fd40051#2d908ec36cd41521a28f7f5fb5dc95499fd40051"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"cfg-if",
|
||||
|
||||
@@ -1,6 +1,32 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Do not run this script if you don't have at least 32 GiB of system memory.
|
||||
# This is the translation tool intended for machine-translating strings.
|
||||
#
|
||||
# ###########################
|
||||
# # Adding new translations #
|
||||
# ###########################
|
||||
#
|
||||
# If you want to add a new language, follow these steps:
|
||||
#
|
||||
# 1. Include the language in `wlx-common/src/locale.rs`:
|
||||
# - add your entry in `enum Language`
|
||||
# - add your entry in Language::code() function
|
||||
# - add your language code in Language::add_codes() function
|
||||
#
|
||||
# 2. Create a new template file
|
||||
# - Add your language code in `scripts/translator/templates/<lang code>.json`
|
||||
# (you can copy one of nearby files and adapt them accordingly)
|
||||
#
|
||||
# 3. Modify this very file
|
||||
# - Go to the bottom and add your language code entry here too
|
||||
#
|
||||
# 4. Run the script (it will hint you which LANG_PATHs are supported)
|
||||
#
|
||||
# ############################################
|
||||
# # Running machine translations (local LLM) #
|
||||
# ############################################
|
||||
#
|
||||
# Do not run this script if you don't have at least ~16 GiB of free system memory.
|
||||
# Submitting PRs that lack translated strings is okay if you don't meet the
|
||||
# system requirements to run this script, or if you simply prefer not to; we are
|
||||
# regularly updating the missing translation strings anyway.
|
||||
@@ -8,15 +34,18 @@
|
||||
# Base language: English (en.json)
|
||||
#
|
||||
# This tool expects llama.cpp server being present (llama-server) at port 8080.
|
||||
#
|
||||
# Currently we're using Gemma 4 for machine translations.
|
||||
# Model URL:
|
||||
# https://huggingface.co/unsloth/gemma-4-31B-it-GGUF
|
||||
# Recommended quantization: Q4_K_M
|
||||
#
|
||||
|
||||
set -e
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
bun install
|
||||
|
||||
# model URL:
|
||||
# https://huggingface.co/unsloth/gemma-4-31B-it-GGUF
|
||||
# you can specify your own if you want to.
|
||||
if [ -z "${MODEL}" ]; then
|
||||
export MODEL="gemma-4-31B-it-Q4_K_M"
|
||||
fi
|
||||
|
||||
+7
-1
@@ -109,7 +109,13 @@ smithay-clipboard = "0.7.3"
|
||||
sysinfo = { version = "0.39.6" }
|
||||
thiserror = "2.0.18"
|
||||
tracing = "0.1.44"
|
||||
whisper-rs = { version = "0.16.0", features = ["vulkan"], optional = true }
|
||||
whisper-rs = {
|
||||
# version = "0.16.0",
|
||||
git = "https://github.com/wayvr-org/whisper-rs.git",
|
||||
rev = "2d908ec36cd41521a28f7f5fb5dc95499fd40051",
|
||||
features = ["vulkan"],
|
||||
optional = true
|
||||
}
|
||||
xcb = {
|
||||
version = "1.7.0",
|
||||
features = [
|
||||
|
||||
@@ -21,7 +21,7 @@ use smithay::{
|
||||
use wgui::log::LogErr;
|
||||
use xkbcommon::xkb;
|
||||
|
||||
use crate::backend::wayvr::{ExternalProcessRequest, WayVRTask};
|
||||
use crate::backend::wayvr::WayVRTask;
|
||||
|
||||
use super::{
|
||||
ProcessWayVREnv,
|
||||
@@ -32,6 +32,7 @@ use super::{
|
||||
pub struct WayVRClient {
|
||||
pub client: wayland_server::Client,
|
||||
pub pid: u32,
|
||||
pub process: process::ProcessHandle,
|
||||
}
|
||||
|
||||
pub struct WayVRCompositor {
|
||||
@@ -160,16 +161,17 @@ impl WayVRCompositor {
|
||||
let process_env = get_wayvr_env_from_pid(credentials.pid)?;
|
||||
|
||||
// Find suitable auth key from the process list
|
||||
for (_, process) in processes {
|
||||
if let process::Process::Managed(process) = &process
|
||||
for (handle, process) in processes.iter() {
|
||||
if let process::Process::Managed(process) = process
|
||||
&& let Some(auth_key) = &process_env.display_auth
|
||||
{
|
||||
// Find process with matching auth key
|
||||
if process.auth_key.as_str() == auth_key {
|
||||
// Add client
|
||||
// Associate client now, instead of trying to match env later
|
||||
self.add_client(WayVRClient {
|
||||
client,
|
||||
pid: credentials.pid as u32,
|
||||
process: handle,
|
||||
});
|
||||
return Ok(());
|
||||
}
|
||||
@@ -178,18 +180,15 @@ impl WayVRCompositor {
|
||||
|
||||
// This is a new process which we didn't met before.
|
||||
// Treat external processes exclusively (spawned by the user or external program)
|
||||
log::warn!(
|
||||
"External process ID {} connected to this Wayland server",
|
||||
credentials.pid
|
||||
);
|
||||
|
||||
self.state
|
||||
.wayvr_tasks
|
||||
.send(WayVRTask::NewExternalProcess(ExternalProcessRequest {
|
||||
env: process_env,
|
||||
client,
|
||||
pid: credentials.pid as u32,
|
||||
}));
|
||||
let pid = credentials.pid as u32;
|
||||
log::warn!("External process ID {pid} connected to this Wayland server");
|
||||
let process =
|
||||
processes.insert(process::Process::External(process::ExternalProcess { pid }));
|
||||
self.add_client(WayVRClient {
|
||||
client,
|
||||
pid,
|
||||
process,
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -118,14 +118,6 @@ pub struct ProcessWayVREnv {
|
||||
pub display_name: Option<String>, // Externally spawned process by a user script
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ExternalProcessRequest {
|
||||
#[allow(dead_code)]
|
||||
pub env: ProcessWayVREnv,
|
||||
pub client: wayland_server::Client,
|
||||
pub pid: u32,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum WayVRTask {
|
||||
NewToplevel(ClientId, ToplevelSurface),
|
||||
@@ -133,7 +125,6 @@ pub enum WayVRTask {
|
||||
MinimizeRequest(ClientId, ToplevelSurface),
|
||||
TitleChange(ClientId, ToplevelSurface),
|
||||
VisibilityChange(window::WindowHandle, bool),
|
||||
NewExternalProcess(ExternalProcessRequest),
|
||||
ProcessTerminationRequest(process::ProcessHandle, KillSignal),
|
||||
CloseWindowRequest(window::WindowHandle),
|
||||
DndStarted {
|
||||
@@ -173,10 +164,6 @@ pub enum PointerFocusTarget {
|
||||
None,
|
||||
}
|
||||
|
||||
pub enum TickTask {
|
||||
NewExternalProcess(ExternalProcessRequest), // Call WayVRCompositor::add_client after receiving this message
|
||||
}
|
||||
|
||||
const KEY_REPEAT_DELAY: i32 = 500;
|
||||
const KEY_REPEAT_RATE: i32 = 50;
|
||||
const WAYVR_SCREEN_RES: [i32; 2] = [2560, 1440];
|
||||
@@ -325,26 +312,29 @@ impl WvrServerState {
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
#[allow(clippy::significant_drop_tightening)]
|
||||
pub fn tick_events(app: &mut AppState) -> anyhow::Result<Vec<TickTask>> {
|
||||
let mut tasks: Vec<TickTask> = Vec::new();
|
||||
|
||||
pub fn tick_events(app: &mut AppState) -> anyhow::Result<()> {
|
||||
let Some(wvr_server) = app.wvr_server.as_mut() else {
|
||||
return Ok(tasks);
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
app.ipc_server.tick(&mut ipc_server::TickParams {
|
||||
wvr_server,
|
||||
input_state: &app.input_state,
|
||||
tasks: &mut tasks,
|
||||
signals: &app.wayvr_signals,
|
||||
hid_wrapper: &mut app.hid_provider,
|
||||
});
|
||||
|
||||
// Tick all child processes
|
||||
// Keep launch records while wl client is attached
|
||||
let attached_processes: HashSet<_> = wvr_server
|
||||
.manager
|
||||
.clients
|
||||
.iter()
|
||||
.map(|client| client.process)
|
||||
.collect();
|
||||
let mut to_remove: SmallVec<[process::ProcessHandle; 2]> = SmallVec::new();
|
||||
|
||||
for (handle, process) in &mut wvr_server.processes {
|
||||
if !process.is_running() {
|
||||
if !process.is_running() && !attached_processes.contains(&handle) {
|
||||
to_remove.push(handle);
|
||||
}
|
||||
}
|
||||
@@ -356,9 +346,6 @@ impl WvrServerState {
|
||||
|
||||
while let Some(task) = wvr_server.tasks.read() {
|
||||
match task {
|
||||
WayVRTask::NewExternalProcess(req) => {
|
||||
tasks.push(TickTask::NewExternalProcess(req));
|
||||
}
|
||||
WayVRTask::NewToplevel(client_id, toplevel) => {
|
||||
let toplevel = Rc::new(toplevel);
|
||||
|
||||
@@ -368,15 +355,14 @@ impl WvrServerState {
|
||||
continue;
|
||||
}
|
||||
|
||||
let Some(process_handle) =
|
||||
process::find_by_pid(&wvr_server.processes, client.pid)
|
||||
else {
|
||||
let process_handle = client.process;
|
||||
if !wvr_server.processes.contains_key(process_handle) {
|
||||
log::error!(
|
||||
"WayVR window creation failed: Unexpected process ID {}. It wasn't registered before.",
|
||||
"WayVR window creation failed: Process for PID {} was removed after the client connected.",
|
||||
client.pid
|
||||
);
|
||||
continue;
|
||||
};
|
||||
}
|
||||
|
||||
let output_bounds = wvr_server.manager.state.output_logical_size();
|
||||
|
||||
@@ -601,7 +587,7 @@ impl WvrServerState {
|
||||
}
|
||||
let Some(window_handle) = wvr_server.wm.find_window_handle(&toplevel)
|
||||
else {
|
||||
log::warn!("MinimizeRequest: Couldn't find matching window handle");
|
||||
log::warn!("TitleChange: Couldn't find matching window handle");
|
||||
continue;
|
||||
};
|
||||
if let Some(oid) = wvr_server.window_to_overlay.get(&window_handle) {
|
||||
@@ -703,7 +689,7 @@ impl WvrServerState {
|
||||
|
||||
wvr_server.ticks += 1;
|
||||
|
||||
Ok(tasks)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn config_changed(&mut self, config: &GeneralConfig) {
|
||||
@@ -1307,11 +1293,6 @@ impl WvrServerState {
|
||||
self.manager.state.set_clipboard_text(content);
|
||||
}
|
||||
|
||||
pub fn add_external_process(&mut self, pid: u32) -> process::ProcessHandle {
|
||||
self.processes
|
||||
.insert(process::Process::External(process::ExternalProcess { pid }))
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn spawn_process(
|
||||
&mut self,
|
||||
|
||||
@@ -87,12 +87,14 @@ impl Process {
|
||||
|
||||
impl Drop for WayVRProcess {
|
||||
fn drop(&mut self) {
|
||||
log::info!(
|
||||
"Sending SIGTERM (graceful exit) to process {} ({})",
|
||||
self.child.id(),
|
||||
self.exec_path.as_str()
|
||||
);
|
||||
self.kill(libc::SIGTERM);
|
||||
if self.is_running() {
|
||||
log::info!(
|
||||
"Sending SIGTERM (graceful exit) to process {} ({})",
|
||||
self.child.id(),
|
||||
self.exec_path.as_str()
|
||||
);
|
||||
self.kill(libc::SIGTERM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,9 +129,11 @@ impl WayVRProcess {
|
||||
}
|
||||
|
||||
fn kill(&mut self, signal: i32) {
|
||||
unsafe {
|
||||
// Gracefully stop process
|
||||
libc::kill(self.child.id() as i32, signal);
|
||||
if self.is_running() {
|
||||
unsafe {
|
||||
// Gracefully stop process
|
||||
libc::kill(self.child.id() as i32, signal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-23
@@ -1,6 +1,6 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::backend::wayvr::{self, WayVRTask, WvrServerState};
|
||||
use crate::backend::wayvr::{WayVRTask, WvrServerState};
|
||||
use wayvr_ipc::packet_client::{HandsfreeMode, HandsfreeParams};
|
||||
use wayvr_ipc::packet_server::PacketServer;
|
||||
use wlx_common::config::HandsfreePointer;
|
||||
@@ -15,24 +15,6 @@ use crate::{
|
||||
windowing::{OverlaySelector, manager::OverlayWindowManager},
|
||||
};
|
||||
|
||||
fn process_tick_tasks(
|
||||
tick_tasks: Vec<backend::wayvr::TickTask>,
|
||||
server_state: &mut WvrServerState,
|
||||
) {
|
||||
for tick_task in tick_tasks {
|
||||
match tick_task {
|
||||
backend::wayvr::TickTask::NewExternalProcess(request) => {
|
||||
log::info!("Registering external process with PID {}", request.pid);
|
||||
server_state.add_external_process(request.pid);
|
||||
server_state.manager.add_client(wayvr::client::WayVRClient {
|
||||
client: request.client,
|
||||
pid: request.pid,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tick_events<O>(
|
||||
app: &mut AppState,
|
||||
overlays: &mut OverlayWindowManager<O>,
|
||||
@@ -135,10 +117,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
let tick_tasks = WvrServerState::tick_events(app)?;
|
||||
if let Some(wayvr_server) = app.wvr_server.as_mut() {
|
||||
process_tick_tasks(tick_tasks, wayvr_server);
|
||||
}
|
||||
WvrServerState::tick_events(app)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -89,8 +89,6 @@ fn read_payload(conn: &mut local_socket::Stream, size: u32) -> anyhow::Result<Op
|
||||
|
||||
pub struct TickParams<'a> {
|
||||
pub wvr_server: &'a mut WvrServerState,
|
||||
#[allow(dead_code)]
|
||||
pub tasks: &'a mut Vec<wayvr::TickTask>,
|
||||
pub signals: &'a SyncEventQueue<WayVRSignal>,
|
||||
pub input_state: &'a InputState,
|
||||
pub hid_wrapper: &'a mut HidWrapper,
|
||||
|
||||
Reference in new issue
Block a user