From 390338c4a5be80da3ed182449ee54487c0150c72 Mon Sep 17 00:00:00 2001 From: galister <22305755+galister@users.noreply.github.com> Date: Thu, 8 Jan 2026 20:47:52 +0900 Subject: [PATCH] keyboard middle click setting; docs, readme & logs --- README.md | 35 ++-- dash-frontend/assets/lang/en.json | 3 + dash-frontend/src/tab/settings.rs | 14 ++ wlx-common/src/config.rs | 14 ++ wlx-overlay-s/src/config.rs | 6 +- wlx-overlay-s/src/gui/README.md | 89 +++++++- .../src/overlays/keyboard/builder.rs | 7 + wlx-overlay-s/src/overlays/keyboard/layout.rs | 13 +- wlx-overlay-s/src/overlays/keyboard/mod.rs | 27 ++- wlx-overlay-s/src/overlays/screen/backend.rs | 5 +- wlx-overlay-s/src/res/config.yaml | 195 ++++++++---------- 11 files changed, 256 insertions(+), 152 deletions(-) diff --git a/README.md b/README.md index 29241a70..98a908c8 100644 --- a/README.md +++ b/README.md @@ -56,8 +56,9 @@ For users specifically running **SteamVR via Steam Flatpak**, follow these steps **When the screen share pop-up appears, check your notifications or the terminal and select the screens in the order it requests.** In case screens were selected in the wrong order: - -- `rm ~/.config/wlxoverlay/conf.d/pw_tokens.yaml` then restart +- Go to Settings and press `Clear PipeWire tokens` and then `Restart software` +- Pay attention to your notifications, it tells you in which order to pick the screens. +- If notifications don't show, try start Wlx from the terminal and look for instructions in there. **WiVRn users**: Select WlxOverlay-S from the `Application` drop-down. If there's no such entry, select `Custom` and browse to your WlxOverlay-S executable or AppImage. @@ -161,29 +162,31 @@ Check [here](https://github.com/galister/wlx-overlay-s/wiki/Troubleshooting) for ### Mouse is not where it should be -X11 users: +If the mouse is moving on a completely different screen, the screens were likely selected in the wrong order: +- Go to Settings and press `Clear PipeWire tokens` and then `Restart software` +- Pay attention to your notifications, it tells you in which order to pick the screens. +- If notifications don't show, try start Wlx from the terminal and look for instructions in there. +COSMIC destkop: +- Due to limitations with COSMIC, the mouse can only move on a single display. + +X11 users: - Might be dealing with a [Phantom Monitor](https://wiki.archlinux.org/title/Xrandr#Disabling_phantom_monitor). - DPI scaling is not supported and will mess with the mouse. - Upright screens are not supported and will mess with the mouse. -Other desktops: The screens may have been selected in the wrong order, see [First Start](#first-start). +### Screens are blank or black or frozen on Steam Link -### Crashes, blank screens +As of SteamVR version 2.14.x, PipeWire capture no longer works when using Steam Link. -There are some driver-desktop combinations that don't play nice with DMA-buf capture. +We're unable to completely troubleshoot how and why Steam Link interferes with PipeWire, so consider the following workarounds for the time being: +- Use another streamer, such as WiVRn or ALVR +- If your desktop [supports ScreenCopy](https://wayland.app/protocols/wlr-screencopy-unstable-v1#compositor-support), go to Settings and set `Wayland capture method` to `ScreenCopy` +- If your desktop has an X11 mode, try using that -Disabling DMA-buf capture is a good first step to try when encountering an app crash or gpu driver reset. +### Modifiers get stuck -```bash -echo 'capture_method: pw_fallback' > ~/.config/wlxoverlay/conf.d/pw_fallback.yaml -``` - -Without DMA-buf capture, capturing screens takes CPU power, so let's try and not show too many screens at the same time. - -### Modifiers get stuck, mouse clicks stop working on KDE Plasma - -We are not sure what causes this, but it only happens on KDE Plasma. Restarting the overlay fixes this. +Hiding the keyboard will un-press all of its buttons. Alternatively, go to Settings and use the `Restart software` button. ### X11 limitations diff --git a/dash-frontend/assets/lang/en.json b/dash-frontend/assets/lang/en.json index 77e1bb57..8f70c46a 100644 --- a/dash-frontend/assets/lang/en.json +++ b/dash-frontend/assets/lang/en.json @@ -74,6 +74,9 @@ "CAPTURE_METHOD": "Wayland screen capture", "CAPTURE_METHOD_HELP": "Try changing this if experiencing\nblack or glitchy screens", + "KEYBOARD_MIDDLE_CLICK": "Keyboard middle click", + "KEYBOARD_MIDDLE_CLICK_HELP": "Modifier to use when typing\nwith purple laser", + "OPTION": { "PIPEWIRE_HELP": "Fast GPU capture. Recommended", "PW_FALLBACK_HELP": "Slow. Try in case PipeWire GPU doesn't work", diff --git a/dash-frontend/src/tab/settings.rs b/dash-frontend/src/tab/settings.rs index d26bd9c2..aa76391f 100644 --- a/dash-frontend/src/tab/settings.rs +++ b/dash-frontend/src/tab/settings.rs @@ -168,6 +168,7 @@ enum SettingType { OpaqueBackground, XwaylandByDefault, CaptureMethod, + KeyboardMiddleClick, } impl SettingType { @@ -226,6 +227,10 @@ impl SettingType { Self::CaptureMethod => { config.capture_method = wlx_common::config::CaptureMethod::from_str(value).expect("Invalid enum value!") } + Self::KeyboardMiddleClick => { + config.keyboard_middle_click_mode = + wlx_common::config::AltModifier::from_str(value).expect("Invalid enum value!") + } _ => panic!("Requested enum for non-enum SettingType"), } } @@ -233,6 +238,7 @@ impl SettingType { fn get_enum_title<'a>(self, config: &'a mut GeneralConfig) -> Translation { match self { Self::CaptureMethod => Self::get_enum_title_inner(config.capture_method), + Self::KeyboardMiddleClick => Self::get_enum_title_inner(config.keyboard_middle_click_mode), _ => panic!("Requested enum for non-enum SettingType"), } } @@ -291,6 +297,7 @@ impl SettingType { Self::OpaqueBackground => Ok("APP_SETTINGS.OPAQUE_BACKGROUND"), Self::XwaylandByDefault => Ok("APP_SETTINGS.XWAYLAND_BY_DEFAULT"), Self::CaptureMethod => Ok("APP_SETTINGS.CAPTURE_METHOD"), + Self::KeyboardMiddleClick => Ok("APP_SETTINGS.KEYBOARD_MIDDLE_CLICK"), } } @@ -308,6 +315,7 @@ impl SettingType { Self::UsePassthrough => Some("APP_SETTINGS.USE_PASSTHROUGH_HELP"), Self::ScreenRenderDown => Some("APP_SETTINGS.SCREEN_RENDER_DOWN_HELP"), Self::CaptureMethod => Some("APP_SETTINGS.CAPTURE_METHOD_HELP"), + Self::KeyboardMiddleClick => Some("APP_SETTINGS.KEYBOARD_MIDDLE_CLICK_HELP"), _ => None, } } @@ -618,6 +626,12 @@ impl TabSettings { slider_f32!(mp, c, SettingType::XrClickSensitivity, 0.1, 1.0, 0.1); slider_f32!(mp, c, SettingType::XrClickSensitivityRelease, 0.1, 1.0, 0.1); slider_i32!(mp, c, SettingType::ClickFreezeTimeMs, 0, 500, 50); + dropdown!( + mp, + c, + SettingType::KeyboardMiddleClick, + wlx_common::config::AltModifier::VARIANTS + ); let c = category!(mp, root, "APP_SETTINGS.MISC", "dashboard/blocks.svg")?; checkbox!(mp, c, SettingType::XwaylandByDefault); diff --git a/wlx-common/src/config.rs b/wlx-common/src/config.rs index f25e9532..7e1d7b35 100644 --- a/wlx-common/src/config.rs +++ b/wlx-common/src/config.rs @@ -30,6 +30,17 @@ pub enum CaptureMethod { ScreenCopy, } +#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize, AsRefStr, EnumString, EnumProperty, VariantArray)] +pub enum AltModifier { + #[default] + None, + Shift, + Ctrl, + Alt, + Super, + Meta, +} + #[derive(Clone, Serialize, Deserialize)] pub struct SerializedWindowSet { pub name: Arc, @@ -270,4 +281,7 @@ pub struct GeneralConfig { #[serde(default)] pub context_menu_hold_and_release: bool, + + #[serde(default)] + pub keyboard_middle_click_mode: AltModifier, } diff --git a/wlx-overlay-s/src/config.rs b/wlx-overlay-s/src/config.rs index 72bdf98d..050a0388 100644 --- a/wlx-overlay-s/src/config.rs +++ b/wlx-overlay-s/src/config.rs @@ -4,7 +4,9 @@ use serde::{Deserialize, Serialize}; use std::path::PathBuf; use wlx_common::{ astr_containers::AStrMap, - config::{CaptureMethod, GeneralConfig, SerializedWindowSet, SerializedWindowStates}, + config::{ + AltModifier, CaptureMethod, GeneralConfig, SerializedWindowSet, SerializedWindowStates, + }, config_io, overlays::BackendAttribValue, }; @@ -139,6 +141,7 @@ pub struct AutoSettings { pub xwayland_by_default: bool, pub context_menu_hold_and_release: bool, pub capture_method: CaptureMethod, + pub keyboard_middle_click_mode: AltModifier, } fn get_settings_path() -> PathBuf { @@ -183,6 +186,7 @@ pub fn save_settings(config: &GeneralConfig) -> anyhow::Result<()> { xwayland_by_default: config.xwayland_by_default, context_menu_hold_and_release: config.context_menu_hold_and_release, capture_method: config.capture_method, + keyboard_middle_click_mode: config.keyboard_middle_click_mode, }; let json = serde_json::to_string_pretty(&conf).unwrap(); // want panic diff --git a/wlx-overlay-s/src/gui/README.md b/wlx-overlay-s/src/gui/README.md index 65e51cc6..ff41ccf9 100644 --- a/wlx-overlay-s/src/gui/README.md +++ b/wlx-overlay-s/src/gui/README.md @@ -99,10 +99,6 @@ Available argument value types (case insensitive): - Float: `1f32`, `1.0f32`, etc - Double: `1f64`, `1.0f64`, etc -##### `::ShutDown` - -Gracefully shuts down WlxOverlay-S. Useful when using an auto-restart script. - ##### `::SendKey ` Sends a key using the virtual keyboard. If WayVR is focused, the key is sent to the WayVR app. @@ -122,3 +118,88 @@ Recenters the STAGE space position so that the HMD is in the center. Does not mo Adjusts the level of floor for STAGE and LOCAL_FLOOR spaces. The user is asked to place one controller on the floor. + +##### `::ContextMenuOpen ` + +Opens the `` of the given name at the location of the click. + +##### `::ContextMenuClose` + +Closes any active context menus. + +##### `::ElementSetDisplay ` + +Sets the visiblitity of the element with `id`. + +##### `::SetToggle ` + +If the given set is visible, it will be hidden. + +Otherwise, it will be set visible. + +##### `::SetSwitch ` + +Switch to the given set. If the set is already visible, nothing happens. + +##### `::AddSet` + +Add a new set and switch to it. The keyboard will be set to visible. + +##### `::DeleteSet` + +Hides the current set, then deletes it. + +##### `::DashToggle` + +Toggle the dashboard + +##### `::EditToggle` + +Toggle edit mode + +##### `::NewMirror` + +Opens a new PipeWire mirror (Wayland-only) + +##### `::CleanupMirrors` + +Destroys all mirrors that are not currently visible (including those that are in a different set). + +##### `::Restart` + +Restarts WlxOverlay-S, reloading all settings. + +##### `::ShutDown` + +Gracefully shuts down WlxOverlay-S. + +##### `::OverlayReset ` + +Resets the position of the given overlay and makes it visible. + +##### `::OverlayToggle ` + +Toggle the visibility of this overlay for the current set + +##### `::OverlayDrop ` + +Destroys the overlay permanently. Mostly useful for mirrors. + +##### `::CustomOverlayReload ` + +If this is a custom overlay, reloads its XML from disk. + +##### `::WvrOverlayCloseWindow ` + +If this is an application, send a close window request to its wl_surface (e.a. X'ing the window) + +##### `::WvrOverlayTermProcess ` + +If the overlay belongs to an application, sends SIGTERM (graceful exit request) to its process. + +##### `::WvrOverlayKillProcess ` + +If the overlay belongs to an application, sends SIGKILL (forced exit request) to its process. + +Also destroys all overlays belonging to the process. + diff --git a/wlx-overlay-s/src/overlays/keyboard/builder.rs b/wlx-overlay-s/src/overlays/keyboard/builder.rs index bb83c16b..d08245b1 100644 --- a/wlx-overlay-s/src/overlays/keyboard/builder.rs +++ b/wlx-overlay-s/src/overlays/keyboard/builder.rs @@ -6,8 +6,10 @@ use crate::{ panel::{GuiPanel, NewGuiPanelParams}, timer::GuiTimer, }, + overlays::keyboard::alt_modifier_to_key, state::AppState, subsystem::hid::XkbKeymap, + windowing::backend::OverlayEventData, }; use anyhow::Context; use glam::{FloatExt, Mat4, Vec2, vec2, vec3}; @@ -281,6 +283,11 @@ pub(super) fn create_keyboard_panel( panel.process_custom_elems(app); } + if matches!(event_data, OverlayEventData::SettingsChanged) { + panel.state.alt_modifier = + alt_modifier_to_key(app.session.config.keyboard_middle_click_mode); + } + panel.layout.process_alterables(alterables)?; Ok(()) })); diff --git a/wlx-overlay-s/src/overlays/keyboard/layout.rs b/wlx-overlay-s/src/overlays/keyboard/layout.rs index f210103f..11c5e163 100644 --- a/wlx-overlay-s/src/overlays/keyboard/layout.rs +++ b/wlx-overlay-s/src/overlays/keyboard/layout.rs @@ -2,6 +2,7 @@ use std::{collections::HashMap, str::FromStr, sync::LazyLock}; use regex::Regex; use serde::{Deserialize, Serialize}; +use wlx_common::config::AltModifier; use crate::{ config::{ConfigType, load_known_yaml}, @@ -232,18 +233,6 @@ pub(super) struct KeyData { pub(super) cap_type: KeyCapType, } -#[derive(Debug, Default, Clone, Copy, Deserialize, Serialize)] -#[repr(usize)] -pub enum AltModifier { - #[default] - None, - Shift, - Ctrl, - Alt, - Super, - Meta, -} - #[derive(Debug)] pub enum KeyCapType { /// Label an SVG diff --git a/wlx-overlay-s/src/overlays/keyboard/mod.rs b/wlx-overlay-s/src/overlays/keyboard/mod.rs index 5975d1b5..5b48cbe3 100644 --- a/wlx-overlay-s/src/overlays/keyboard/mod.rs +++ b/wlx-overlay-s/src/overlays/keyboard/mod.rs @@ -12,7 +12,7 @@ use crate::{ task::{OverlayTask, TaskType}, }, gui::panel::{GuiPanel, overlay_list::OverlayList, set_list::SetList}, - overlays::keyboard::{builder::create_keyboard_panel, layout::AltModifier}, + overlays::keyboard::builder::create_keyboard_panel, state::AppState, subsystem::{ dbus::DbusConnector, @@ -34,8 +34,11 @@ use wgui::{ drawing, event::{InternalStateChangeEvent, MouseButton, MouseButtonIndex}, }; -use wlx_common::overlays::{BackendAttrib, BackendAttribValue}; use wlx_common::windowing::{OverlayWindowState, Positioning}; +use wlx_common::{ + config::AltModifier, + overlays::{BackendAttrib, BackendAttribValue}, +}; pub mod builder; mod layout; @@ -48,14 +51,7 @@ pub fn create_keyboard(app: &mut AppState, wayland: bool) -> anyhow::Result SHIFT, - AltModifier::Ctrl => CTRL, - AltModifier::Alt => ALT, - AltModifier::Super => SUPER, - AltModifier::Meta => META, - _ => 0, - }, + alt_modifier: alt_modifier_to_key(app.session.config.keyboard_middle_click_mode), processes: vec![], overlay_list: OverlayList::default(), set_list: SetList::default(), @@ -122,6 +118,17 @@ pub fn create_keyboard(app: &mut AppState, wayland: bool) -> anyhow::Result KeyModifier { + match m { + AltModifier::Shift => SHIFT, + AltModifier::Ctrl => CTRL, + AltModifier::Alt => ALT, + AltModifier::Super => SUPER, + AltModifier::Meta => META, + _ => 0, + } +} + new_key_type! { struct KeyboardPanelKey; } diff --git a/wlx-overlay-s/src/overlays/screen/backend.rs b/wlx-overlay-s/src/overlays/screen/backend.rs index 84c23dbc..06ee3036 100644 --- a/wlx-overlay-s/src/overlays/screen/backend.rs +++ b/wlx-overlay-s/src/overlays/screen/backend.rs @@ -175,10 +175,7 @@ impl OverlayBackend for ScreenBackend { &Vec::new() } else { log::warn!( - "Using DMA-buf capture. If screens are blank for you, switch to SHM using:" - ); - log::warn!( - "echo 'capture_method: pw_fallback' > ~/.config/wlxoverlay/conf.d/pw_fallback.yaml" + "Using GPU capture. If you're having issues with screens, go to the Dashboard's Settings tab and switch 'Wayland capture method' to a CPU option!" ); &app.gfx_extras.drm_formats diff --git a/wlx-overlay-s/src/res/config.yaml b/wlx-overlay-s/src/res/config.yaml index b6016c82..14fd1176 100644 --- a/wlx-overlay-s/src/res/config.yaml +++ b/wlx-overlay-s/src/res/config.yaml @@ -5,7 +5,85 @@ # In case you're not getting the expected result, # check the logs at /tmp/wlx.log for parsing errors. -################ EXPERIENCE ################ +## Only if built with `osc` feature. What port to send OSC messages to. +#osc_out_port: 9000 + +## Set your preferred watch timezones here. +#timezones: +# - "Europe/Oslo" +# - "America/New_York" + +## On most desktops, WlxOverlay-S is able to pick up your keymap via wayland. (Especially when using Fcitx5!) +## However, if this does not happen, you might want to set your keymap by hand. +## When using a simple layout: +#default_keymap: us +# +## When defining a layout-variant pair, separate using a dash: +#default_keymap: us-colemak_dh + +## Path to read the custom theme from, relative to `~/.config/wlxoverlay` +#theme_path: "theme" + +## These can be used to control the color theme of WlxOverlay-S. +#color_text: "#ffffff" +#color_accent: "#008cff" +#color_danger: "#ff3300" +#color_faded: "#668299" +#color_background: "#010206" + +## Path to custom skybox texture, relative to `~/.config/wlxoverlay` +#skybox_texture: "" + +## User-defined list of custom overlays that should be created. +## Each entry must correspond to an XML file at: {theme_path}/gui/{entry}.xml +#custom_panels: +# - "test" + +## The alt_click binding can be used to execute a program of choice +## These are not default, but example values. +#alt_click_down: ["bash", "-c", "echo x"] +#alt_click_up: ["bash", "-c", "echo y"] + +## Example for quick-calibration with `motoc`: +#alt_click_down: +# [ +# "motoc", +# "calibrate", +# "--src", +# "WiVRn HMD", +# "--dst", +# "LHR-AABBCCDD", +# "--samples", +# "200", +# ] + +## Set what kind of notifications to show and what to hide +#notification_topics: +# System: Center +# DesktopNotification: Center +# XSNotification: Center +# IpdChange: Hide + +## Path to a custom notification sound, relative to `~/.config/wlxoverlay` +#notification_sound: "" + +## If `screen_render_down` is enabled, +## controls the maximum height of the screen +#screen_max_height: 1440 + +## Don't move the mouse more often than this value +## helps to avoid unnecessary load when pairing +## a high-refresh screen with a lower-refresh hmd +#mouse_move_interval_ms: 10 + +################ MANAGED FROM DASHBOARD ################ +################ MANAGED FROM DASHBOARD ################ +################ MANAGED FROM DASHBOARD ################ +################ MANAGED FROM DASHBOARD ################ + +# ANYTHING BELOW HERE IS MANAGED FROM THE DASHBOARD. +# The settings are here for reference only. +# Probably don't include them in your config file. ## The bottom of the watch will list sets instead of overlays. #sets_on_watch: false @@ -51,111 +129,33 @@ ## 0.1 → too much smoothing #pointer_lerp_factor: 0.3 -## Only if built with `osc` feature. What port to send OSC messages to. -#osc_out_port: 9000 - ## If your upright screen is not displaying correctly, try enabling this. #upright_screen_fix: false ## If you're seeing the cursor twice, try enabling this. #double_cursor_fix: false - -################ TIME ################ - -## Set your preferred watch timezones here. -#timezones: -# - "Europe/Oslo" -# - "America/New_York" - +# ## Use 12h instead of 24h watch. #clock_12h: false -################ KEYBOARD ################ - -## On most desktops, WlxOverlay-S is able to pick up your keymap via wayland. (Especially when using Fcitx5!) -## However, if this does not happen, you might want to set your keymap by hand. - -## When using a simple layout: -#default_keymap: us - -## When defining a layout-variant pair, separate using a dash: -#default_keymap: us-colemak_dh - -## Toggle keyboard click sound -#keyboard_sound_enabled: true - -################ THEMING & CUSTOMIZATION ################ - -## Path to read the custom theme from, relative to `~/.config/wlxoverlay` -#theme_path: "theme" - -## These can be used to control the color theme of WlxOverlay-S. -#color_text: "#ffffff" -#color_accent: "#008cff" -#color_danger: "#ff3300" -#color_faded: "#668299" -#color_background: "#010206" - -## Multiplier for animation speed. 2.0 → double speed, 0.5 → half speed -#animation_speed: 1.0 - -## Adjust this between 0..1 for a more rectangular feel. -#round_multiplier: 1.0 - -## Path to custom skybox texture, relative to `~/.config/wlxoverlay` -#skybox_texture: "" - -## User-defined list of custom overlays that should be created. -## Each entry must correspond to an XML file at: {theme_path}/gui/{entry}.xml -#custom_panels: -# - "test" - -## Alter default scale of various overlays -#keyboard_scale: 1.0 -#desktop_view_scale: 1.0 -#watch_scale: 1.0 - -## Control the fade & visibility of the watch -#watch_view_angle_min: 0.5 -#watch_view_angle_max: 0.7 - -## The alt_click binding can be used to execute a program of choice -## These are not default, but example values. -#alt_click_down: ["bash", "-c", "echo x"] -#alt_click_up: ["bash", "-c", "echo y"] - -## Example for quick-calibration with `motoc`: -#alt_click_down: -# [ -# "motoc", -# "calibrate", -# "--src", -# "WiVRn HMD", -# "--dst", -# "LHR-AABBCCDD", -# "--samples", -# "200", -# ] - -################ NOTIFICATIONS ################ - ## Set whether notifications should be shown at all #notifications_enabled: true ## Set whether notfications should make a sound #notifications_sound_enabled: true -## Set what kind of notifications to show and what to hide -#notification_topics: -# System: Center -# DesktopNotification: Center -# XSNotification: Center -# IpdChange: Hide +## Toggle keyboard click sound +#keyboard_sound_enabled: true -## Path to a custom notification sound, relative to `~/.config/wlxoverlay` -#notification_sound: "" +## Multiplier for animation speed. 2.0 → double speed, 0.5 → half speed +#animation_speed: 1.0 -################ CONTROL TWEAKS ################ +## Adjust this between 0..1 for a more rectangular feel. +#round_multiplier: 1.0 + +## Render screens & mirrors at a lower resolution. +## Avoids aliasing on 4K+ screens, and also saves VRAM +#screen_render_down: false ## For how much time mouse motion events should be stopped after clicking? ## Prevents accidental dragging various GUI elements or links, making it easier to click @@ -190,18 +190,3 @@ ## allowing for moving both pointers off the screens to the keyboard, while keeping the cursor position ## unchanged, for when the desktop is configured to move the focus with the mouse cursor #focus_follows_mouse_mode: false - -################ PERFORMANCE TWEAKS ################ - -## Render screens & mirrors at a lower resolution. -## Avoids aliasing on 4K+ screens, and also saves VRAM -#screen_render_down: false - -## If `screen_render_down` is enabled, -## controls the maximum height of the screen -#screen_max_height: 1440 - -## Don't move the mouse more often than this value -## helps to avoid unnecessary load when pairing -## a high-refresh screen with a lower-refresh hmd -#mouse_move_interval_ms: 10