config: Add invert_scroll_direction and scroll_speed

This commit is contained in:
Aleksander
2025-11-11 12:11:34 +01:00
parent 6169ec9505
commit afc8804aba
16 changed files with 159 additions and 101 deletions

View File

@@ -134,7 +134,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
.borrow_mut() .borrow_mut()
.push_event( .push_event(
&wgui::event::Event::MouseWheel(MouseWheelEvent { &wgui::event::Event::MouseWheel(MouseWheelEvent {
shift: Vec2::new(x, y), delta: Vec2::new(x, y),
pos: mouse / scale, pos: mouse / scale,
device: 0, device: 0,
}), }),
@@ -149,7 +149,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
.borrow_mut() .borrow_mut()
.push_event( .push_event(
&wgui::event::Event::MouseWheel(MouseWheelEvent { &wgui::event::Event::MouseWheel(MouseWheelEvent {
shift: Vec2::new(pos.x as f32 / 5.0, pos.y as f32 / 5.0), delta: Vec2::new(pos.x as f32 / 5.0, pos.y as f32 / 5.0),
pos: mouse / scale, pos: mouse / scale,
device: 0, device: 0,
}), }),

View File

@@ -55,8 +55,8 @@ pub struct MouseUpEvent {
} }
pub struct MouseWheelEvent { pub struct MouseWheelEvent {
pub pos: Vec2, pub pos: Vec2, /* mouse position */
pub shift: Vec2, pub delta: Vec2, /* wheel delta */
pub device: usize, pub device: usize,
} }

View File

@@ -395,7 +395,7 @@ impl WidgetState {
if info.handle_size.x < 1.0 && wheel.pos.x != 0.0 { if info.handle_size.x < 1.0 && wheel.pos.x != 0.0 {
// Horizontal scrolling // Horizontal scrolling
let mult = (1.0 / (l.content_box_width() - info.content_size.x)) * step_pixels; let mult = (1.0 / (l.content_box_width() - info.content_size.x)) * step_pixels;
let new_scroll = (self.data.scrolling_target.x + wheel.shift.x * mult).clamp(0.0, 1.0); let new_scroll = (self.data.scrolling_target.x + wheel.delta.x * mult).clamp(0.0, 1.0);
if self.data.scrolling_target.x != new_scroll { if self.data.scrolling_target.x != new_scroll {
self.data.scrolling_target.x = new_scroll; self.data.scrolling_target.x = new_scroll;
params.alterables.mark_tick(self.obj.get_id()); params.alterables.mark_tick(self.obj.get_id());
@@ -405,7 +405,7 @@ impl WidgetState {
if info.handle_size.y < 1.0 && wheel.pos.y != 0.0 { if info.handle_size.y < 1.0 && wheel.pos.y != 0.0 {
// Vertical scrolling // Vertical scrolling
let mult = (1.0 / (l.content_box_height() - info.content_size.y)) * step_pixels; let mult = (1.0 / (l.content_box_height() - info.content_size.y)) * step_pixels;
let new_scroll = (self.data.scrolling_target.y + wheel.shift.y * mult).clamp(0.0, 1.0); let new_scroll = (self.data.scrolling_target.y + wheel.delta.y * mult).clamp(0.0, 1.0);
if self.data.scrolling_target.y != new_scroll { if self.data.scrolling_target.y != new_scroll {
self.data.scrolling_target.y = new_scroll; self.data.scrolling_target.y = new_scroll;
params.alterables.mark_tick(self.obj.get_id()); params.alterables.mark_tick(self.obj.get_id());

View File

@@ -4,10 +4,11 @@ use std::{collections::VecDeque, time::Instant};
use glam::{Affine3A, Vec2, Vec3, Vec3A, Vec3Swizzles}; use glam::{Affine3A, Vec2, Vec3, Vec3A, Vec3Swizzles};
use smallvec::{smallvec, SmallVec}; use smallvec::{SmallVec, smallvec};
use crate::overlays::anchor::ANCHOR_NAME; use crate::overlays::anchor::ANCHOR_NAME;
use crate::state::{AppSession, AppState}; use crate::state::{AppSession, AppState};
use crate::subsystem::hid::WheelDelta;
use crate::subsystem::input::KeyboardFocus; use crate::subsystem::input::KeyboardFocus;
use crate::windowing::manager::OverlayWindowManager; use crate::windowing::manager::OverlayWindowManager;
use crate::windowing::window::{OverlayWindowData, OverlayWindowState, Positioning}; use crate::windowing::window::{OverlayWindowData, OverlayWindowState, Positioning};
@@ -450,9 +451,27 @@ fn handle_no_hit<O>(
fn handle_scroll<O>(hit: &PointerHit, hovered: &mut OverlayWindowData<O>, app: &mut AppState) { fn handle_scroll<O>(hit: &PointerHit, hovered: &mut OverlayWindowData<O>, app: &mut AppState) {
let pointer = &mut app.input_state.pointers[hit.pointer]; let pointer = &mut app.input_state.pointers[hit.pointer];
if pointer.now.scroll_x.abs() > 0.1 || pointer.now.scroll_y.abs() > 0.1 { if pointer.now.scroll_x.abs() <= 0.1 && pointer.now.scroll_x.abs() <= 0.1 {
let scroll_x = pointer.now.scroll_x; return;
let scroll_y = pointer.now.scroll_y; }
let config = &app.session.config;
let scroll_x = pointer.now.scroll_x
* config.scroll_speed
* if config.invert_scroll_direction_x {
-1.0
} else {
1.0
};
let scroll_y = pointer.now.scroll_y
* config.scroll_speed
* if config.invert_scroll_direction_x {
-1.0
} else {
1.0
};
if app.input_state.pointers[1 - hit.pointer] if app.input_state.pointers[1 - hit.pointer]
.interaction .interaction
.grabbed .grabbed
@@ -476,11 +495,14 @@ fn handle_scroll<O>(hit: &PointerHit, hovered: &mut OverlayWindowData<O>, app: &
hovered_state.curvature = None; hovered_state.curvature = None;
} }
} else { } else {
hovered hovered.config.backend.on_scroll(
.config app,
.backend hit,
.on_scroll(app, hit, scroll_y, scroll_x); WheelDelta {
} x: scroll_x,
y: scroll_y,
},
);
} }
} }

View File

@@ -1,6 +1,6 @@
use std::f32::consts::PI; use std::f32::consts::PI;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc; use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use ash::vk::SubmitInfo; use ash::vk::SubmitInfo;
use glam::{Affine3A, Vec3, Vec3A, Vec4}; use glam::{Affine3A, Vec3, Vec3A, Vec4};
@@ -8,6 +8,7 @@ use idmap::IdMap;
use ovr_overlay::overlay::OverlayManager; use ovr_overlay::overlay::OverlayManager;
use ovr_overlay::sys::ETrackingUniverseOrigin; use ovr_overlay::sys::ETrackingUniverseOrigin;
use vulkano::{ use vulkano::{
VulkanObject,
command_buffer::{ command_buffer::{
CommandBufferBeginInfo, CommandBufferLevel, CommandBufferUsage, RecordingCommandBuffer, CommandBufferBeginInfo, CommandBufferLevel, CommandBufferUsage, RecordingCommandBuffer,
}, },
@@ -15,19 +16,19 @@ use vulkano::{
image::view::ImageView, image::view::ImageView,
image::{Image, ImageLayout}, image::{Image, ImageLayout},
sync::{ sync::{
fence::{Fence, FenceCreateInfo},
AccessFlags, DependencyInfo, ImageMemoryBarrier, PipelineStages, AccessFlags, DependencyInfo, ImageMemoryBarrier, PipelineStages,
fence::{Fence, FenceCreateInfo},
}, },
VulkanObject,
}; };
use wgui::gfx::WGfx; use wgui::gfx::WGfx;
use crate::backend::input::{HoverResult, PointerHit}; use crate::backend::input::{HoverResult, PointerHit};
use crate::graphics::CommandBuffers; use crate::graphics::CommandBuffers;
use crate::state::AppState; use crate::state::AppState;
use crate::subsystem::hid::WheelDelta;
use crate::windowing::Z_ORDER_LINES;
use crate::windowing::backend::{FrameMeta, OverlayBackend, ShouldRender}; use crate::windowing::backend::{FrameMeta, OverlayBackend, ShouldRender};
use crate::windowing::window::{OverlayWindowConfig, OverlayWindowData}; use crate::windowing::window::{OverlayWindowConfig, OverlayWindowData};
use crate::windowing::Z_ORDER_LINES;
use super::overlay::OpenVrOverlayData; use super::overlay::OpenVrOverlayData;
@@ -209,7 +210,7 @@ impl OverlayBackend for LineBackend {
} }
fn on_left(&mut self, _: &mut AppState, _: usize) {} fn on_left(&mut self, _: &mut AppState, _: usize) {}
fn on_pointer(&mut self, _: &mut AppState, _: &PointerHit, _: bool) {} fn on_pointer(&mut self, _: &mut AppState, _: &PointerHit, _: bool) {}
fn on_scroll(&mut self, _: &mut AppState, _: &PointerHit, _: f32, _: f32) {} fn on_scroll(&mut self, _: &mut AppState, _: &PointerHit, _delta: WheelDelta) {}
fn get_interaction_transform(&mut self) -> Option<glam::Affine2> { fn get_interaction_transform(&mut self) -> Option<glam::Affine2> {
None None
} }

View File

@@ -2,13 +2,13 @@ use std::{cell::RefCell, rc::Rc, sync::Arc};
use smithay::{ use smithay::{
backend::renderer::{ backend::renderer::{
element::{
surface::{render_elements_from_surface_tree, WaylandSurfaceRenderElement},
Kind,
},
gles::{ffi, GlesRenderer, GlesTexture},
utils::draw_render_elements,
Bind, Color32F, Frame, Renderer, Bind, Color32F, Frame, Renderer,
element::{
Kind,
surface::{WaylandSurfaceRenderElement, render_elements_from_surface_tree},
},
gles::{GlesRenderer, GlesTexture, ffi},
utils::draw_render_elements,
}, },
input, input,
utils::{Logical, Point, Rectangle, Size, Transform}, utils::{Logical, Point, Rectangle, Size, Transform},
@@ -16,11 +16,13 @@ use smithay::{
}; };
use wayvr_ipc::packet_server; use wayvr_ipc::packet_server;
use crate::{backend::wayvr::time::get_millis, gen_id, windowing::OverlayID}; use crate::{
backend::wayvr::time::get_millis, gen_id, subsystem::hid::WheelDelta, windowing::OverlayID,
};
use super::{ use super::{
client::WayVRCompositor, comp::send_frames_surface_tree, egl_data, event_queue::SyncEventQueue, BlitMethod, WayVRSignal, client::WayVRCompositor, comp::send_frames_surface_tree, egl_data,
process, smithay_wrapper, time, window, BlitMethod, WayVRSignal, event_queue::SyncEventQueue, process, smithay_wrapper, time, window,
}; };
fn generate_auth_key() -> String { fn generate_auth_key() -> String {
@@ -527,7 +529,7 @@ impl Display {
manager.seat_pointer.frame(&mut manager.state); manager.seat_pointer.frame(&mut manager.state);
} }
pub fn send_mouse_scroll(manager: &mut WayVRCompositor, delta_y: f32, delta_x: f32) { pub fn send_mouse_scroll(manager: &mut WayVRCompositor, delta: WheelDelta) {
manager.seat_pointer.axis( manager.seat_pointer.axis(
&mut manager.state, &mut manager.state,
input::pointer::AxisFrame { input::pointer::AxisFrame {
@@ -537,8 +539,8 @@ impl Display {
smithay::backend::input::AxisRelativeDirection::Identical, smithay::backend::input::AxisRelativeDirection::Identical,
), ),
time: 0, time: 0,
axis: (f64::from(delta_x), f64::from(-delta_y)), axis: (f64::from(delta.x), f64::from(-delta.y)),
v120: Some((0, (delta_y * -120.0) as i32)), v120: Some((0, (delta.y * -64.0) as i32)),
stop: (false, false), stop: (false, false),
}, },
); );

View File

@@ -42,7 +42,10 @@ use std::{
use time::get_millis; use time::get_millis;
use wayvr_ipc::{packet_client, packet_server}; use wayvr_ipc::{packet_client, packet_server};
use crate::{state::AppState, subsystem::hid::MODS_TO_KEYS}; use crate::{
state::AppState,
subsystem::hid::{MODS_TO_KEYS, WheelDelta},
};
const STR_INVALID_HANDLE_DISP: &str = "Invalid display handle"; const STR_INVALID_HANDLE_DISP: &str = "Invalid display handle";
@@ -507,8 +510,8 @@ impl WayVRState {
Display::send_mouse_up(&mut self.manager, index); Display::send_mouse_up(&mut self.manager, index);
} }
pub fn send_mouse_scroll(&mut self, delta_y: f32, delta_x: f32) { pub fn send_mouse_scroll(&mut self, delta: WheelDelta) {
Display::send_mouse_scroll(&mut self.manager, delta_y, delta_x); Display::send_mouse_scroll(&mut self.manager, delta);
} }
pub fn send_key(&mut self, virtual_key: u32, down: bool) { pub fn send_key(&mut self, virtual_key: u32, down: bool) {

View File

@@ -7,7 +7,7 @@ use crate::state::LeftRight;
use crate::windowing::set::SerializedWindowSet; use crate::windowing::set::SerializedWindowSet;
use chrono::Offset; use chrono::Offset;
use config::{Config, File}; use config::{Config, File};
use glam::{vec3, Affine3A, Quat, Vec3}; use glam::{Affine3A, Quat, Vec3, vec3};
use idmap::IdMap; use idmap::IdMap;
use log::error; use log::error;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -193,6 +193,15 @@ pub struct GeneralConfig {
#[serde(default = "def_click_freeze_time_ms")] #[serde(default = "def_click_freeze_time_ms")]
pub click_freeze_time_ms: u32, pub click_freeze_time_ms: u32,
#[serde(default = "def_false")]
pub invert_scroll_direction_x: bool,
#[serde(default = "def_false")]
pub invert_scroll_direction_y: bool,
#[serde(default = "def_one")]
pub scroll_speed: f32,
#[serde(default = "def_mouse_move_interval_ms")] #[serde(default = "def_mouse_move_interval_ms")]
pub mouse_move_interval_ms: u32, pub mouse_move_interval_ms: u32,
@@ -343,6 +352,7 @@ impl GeneralConfig {
fn post_load(&self) { fn post_load(&self) {
Self::sanitize_range("keyboard_scale", self.keyboard_scale, 0.05, 5.0); Self::sanitize_range("keyboard_scale", self.keyboard_scale, 0.05, 5.0);
Self::sanitize_range("desktop_view_scale", self.desktop_view_scale, 0.05, 5.0); Self::sanitize_range("desktop_view_scale", self.desktop_view_scale, 0.05, 5.0);
Self::sanitize_range("scroll_speed", self.scroll_speed, 0.01, 10.0);
} }
} }

View File

@@ -1,7 +1,7 @@
use std::{cell::RefCell, rc::Rc, sync::Arc}; use std::{cell::RefCell, rc::Rc, sync::Arc};
use button::setup_custom_button; use button::setup_custom_button;
use glam::{vec2, Affine2, Vec2}; use glam::{Affine2, Vec2, vec2};
use label::setup_custom_label; use label::setup_custom_label;
use vulkano::{command_buffer::CommandBufferUsage, image::view::ImageView}; use vulkano::{command_buffer::CommandBufferUsage, image::view::ImageView};
use wgui::{ use wgui::{
@@ -15,14 +15,15 @@ use wgui::{
layout::{Layout, LayoutParams, WidgetID}, layout::{Layout, LayoutParams, WidgetID},
parser::ParserState, parser::ParserState,
renderer_vk::context::Context as WguiContext, renderer_vk::context::Context as WguiContext,
widget::{label::WidgetLabel, rectangle::WidgetRectangle, EventResult}, widget::{EventResult, label::WidgetLabel, rectangle::WidgetRectangle},
}; };
use crate::{ use crate::{
backend::input::{Haptics, HoverResult, PointerHit, PointerMode}, backend::input::{Haptics, HoverResult, PointerHit, PointerMode},
graphics::{CommandBuffers, ExtentExt}, graphics::{CommandBuffers, ExtentExt},
state::AppState, state::AppState,
windowing::backend::{ui_transform, FrameMeta, OverlayBackend, ShouldRender}, subsystem::hid::WheelDelta,
windowing::backend::{FrameMeta, OverlayBackend, ShouldRender, ui_transform},
}; };
use super::{timer::GuiTimer, timestep::Timestep}; use super::{timer::GuiTimer, timestep::Timestep};
@@ -270,9 +271,9 @@ impl<S: 'static> OverlayBackend for GuiPanel<S> {
}) })
} }
fn on_scroll(&mut self, app: &mut AppState, hit: &PointerHit, delta_y: f32, delta_x: f32) { fn on_scroll(&mut self, app: &mut AppState, hit: &PointerHit, delta: WheelDelta) {
let e = WguiEvent::MouseWheel(MouseWheelEvent { let e = WguiEvent::MouseWheel(MouseWheelEvent {
shift: vec2(delta_x, delta_y), delta: vec2(delta.x, delta.y),
pos: hit.uv * self.layout.content_size, pos: hit.uv * self.layout.content_size,
device: hit.pointer, device: hit.pointer,
}); });

View File

@@ -15,7 +15,7 @@ use crate::{
graphics::CommandBuffers, graphics::CommandBuffers,
gui::panel::GuiPanel, gui::panel::GuiPanel,
state::AppState, state::AppState,
subsystem::hid::{KeyModifier, VirtualKey, ALT, CTRL, META, SHIFT, SUPER}, subsystem::hid::{ALT, CTRL, KeyModifier, META, SHIFT, SUPER, VirtualKey, WheelDelta},
windowing::backend::{FrameMeta, OverlayBackend, ShouldRender}, windowing::backend::{FrameMeta, OverlayBackend, ShouldRender},
}; };
@@ -69,8 +69,8 @@ impl OverlayBackend for KeyboardBackend {
&wgui::event::Event::InternalStateChange(InternalStateChangeEvent { metadata: 0 }), &wgui::event::Event::InternalStateChange(InternalStateChangeEvent { metadata: 0 }),
); );
} }
fn on_scroll(&mut self, app: &mut AppState, hit: &PointerHit, delta_y: f32, delta_x: f32) { fn on_scroll(&mut self, app: &mut AppState, hit: &PointerHit, delta: WheelDelta) {
self.panel.on_scroll(app, hit, delta_y, delta_x); self.panel.on_scroll(app, hit, delta);
} }
fn on_left(&mut self, app: &mut AppState, pointer: usize) { fn on_left(&mut self, app: &mut AppState, pointer: usize) {
self.panel.on_left(app, pointer); self.panel.on_left(app, pointer);

View File

@@ -6,7 +6,7 @@ use std::{
use futures::{Future, FutureExt}; use futures::{Future, FutureExt};
use glam::{Affine2, Affine3A, Vec3}; use glam::{Affine2, Affine3A, Vec3};
use vulkano::image::view::ImageView; use vulkano::image::view::ImageView;
use wlx_capture::pipewire::{pipewire_select_screen, PipewireCapture, PipewireSelectScreenResult}; use wlx_capture::pipewire::{PipewireCapture, PipewireSelectScreenResult, pipewire_select_screen};
use crate::{ use crate::{
backend::{ backend::{
@@ -15,10 +15,11 @@ use crate::{
}, },
graphics::CommandBuffers, graphics::CommandBuffers,
state::{AppSession, AppState}, state::{AppSession, AppState},
subsystem::hid::WheelDelta,
windowing::{ windowing::{
backend::{ui_transform, FrameMeta, OverlayBackend, ShouldRender},
window::{OverlayWindowConfig, OverlayWindowState},
OverlaySelector, OverlaySelector,
backend::{FrameMeta, OverlayBackend, ShouldRender, ui_transform},
window::{OverlayWindowConfig, OverlayWindowState},
}, },
}; };
@@ -138,7 +139,7 @@ impl OverlayBackend for MirrorBackend {
} }
fn on_left(&mut self, _: &mut AppState, _: usize) {} fn on_left(&mut self, _: &mut AppState, _: usize) {}
fn on_pointer(&mut self, _: &mut AppState, _: &PointerHit, _: bool) {} fn on_pointer(&mut self, _: &mut AppState, _: &PointerHit, _: bool) {}
fn on_scroll(&mut self, _: &mut AppState, _: &PointerHit, _: f32, _: f32) {} fn on_scroll(&mut self, _: &mut AppState, _: &PointerHit, _delta: WheelDelta) {}
fn get_interaction_transform(&mut self) -> Option<Affine2> { fn get_interaction_transform(&mut self) -> Option<Affine2> {
self.interaction_transform self.interaction_transform
} }

View File

@@ -1,21 +1,21 @@
use std::{ use std::{
sync::{atomic::AtomicU64, Arc, LazyLock}, sync::{Arc, LazyLock, atomic::AtomicU64},
time::Instant, time::Instant,
}; };
use glam::{vec2, Affine2, Vec2}; use glam::{Affine2, Vec2, vec2};
use vulkano::image::view::ImageView; use vulkano::image::view::ImageView;
use wlx_capture::{frame::Transform, WlxCapture}; use wlx_capture::{WlxCapture, frame::Transform};
use crate::{ use crate::{
backend::input::{HoverResult, PointerHit, PointerMode}, backend::input::{HoverResult, PointerHit, PointerMode},
graphics::{CommandBuffers, ExtentExt}, graphics::{CommandBuffers, ExtentExt},
state::AppState, state::AppState,
subsystem::hid::{MOUSE_LEFT, MOUSE_MIDDLE, MOUSE_RIGHT}, subsystem::hid::{MOUSE_LEFT, MOUSE_MIDDLE, MOUSE_RIGHT, WheelDelta},
windowing::backend::{FrameMeta, OverlayBackend, ShouldRender}, windowing::backend::{FrameMeta, OverlayBackend, ShouldRender},
}; };
use super::capture::{receive_callback, ScreenPipeline, WlxCaptureIn, WlxCaptureOut}; use super::capture::{ScreenPipeline, WlxCaptureIn, WlxCaptureOut, receive_callback};
const CURSOR_SIZE: f32 = 16. / 1440.; const CURSOR_SIZE: f32 = 16. / 1440.;
@@ -246,11 +246,11 @@ impl OverlayBackend for ScreenBackend {
let pos = self.mouse_transform.transform_point2(hit.uv); let pos = self.mouse_transform.transform_point2(hit.uv);
app.hid_provider.inner.mouse_move(pos); app.hid_provider.inner.mouse_move(pos);
} }
fn on_scroll(&mut self, app: &mut AppState, _hit: &PointerHit, delta_y: f32, delta_x: f32) {
app.hid_provider fn on_scroll(&mut self, app: &mut AppState, _hit: &PointerHit, delta: WheelDelta) {
.inner app.hid_provider.inner.wheel(delta);
.wheel((delta_y * 64.) as i32, (delta_x * 64.) as i32);
} }
fn on_left(&mut self, _app: &mut AppState, _hand: usize) {} fn on_left(&mut self, _app: &mut AppState, _hand: usize) {}
fn get_interaction_transform(&mut self) -> Option<Affine2> { fn get_interaction_transform(&mut self) -> Option<Affine2> {

View File

@@ -1,17 +1,17 @@
use glam::{vec3, Affine2, Affine3A, Quat, Vec3}; use glam::{Affine2, Affine3A, Quat, Vec3, vec3};
use smallvec::smallvec; use smallvec::smallvec;
use std::{cell::RefCell, collections::HashMap, rc::Rc, sync::Arc}; use std::{cell::RefCell, collections::HashMap, rc::Rc, sync::Arc};
use vulkano::{ use vulkano::{
buffer::{BufferUsage, Subbuffer}, buffer::{BufferUsage, Subbuffer},
command_buffer::CommandBufferUsage, command_buffer::CommandBufferUsage,
format::Format, format::Format,
image::{view::ImageView, Image, ImageTiling, SubresourceLayout}, image::{Image, ImageTiling, SubresourceLayout, view::ImageView},
}; };
use wayvr_ipc::packet_server::{self, PacketServer, WvrStateChanged}; use wayvr_ipc::packet_server::{self, PacketServer, WvrStateChanged};
use wgui::gfx::{ use wgui::gfx::{
WGfx,
pass::WGfxPass, pass::WGfxPass,
pipeline::{WGfxPipeline, WPipelineCreateInfo}, pipeline::{WGfxPipeline, WPipelineCreateInfo},
WGfx,
}; };
use wlx_capture::frame::{DmabufFrame, FourCC, FrameFormat, FramePlane}; use wlx_capture::frame::{DmabufFrame, FourCC, FrameFormat, FramePlane};
@@ -20,20 +20,19 @@ use crate::{
input::{self, HoverResult}, input::{self, HoverResult},
task::TaskType, task::TaskType,
wayvr::{ wayvr::{
self, display, self, WayVR, WayVRAction, WayVRDisplayClickAction, display,
server_ipc::{gen_args_vec, gen_env_vec}, server_ipc::{gen_args_vec, gen_env_vec},
WayVR, WayVRAction, WayVRDisplayClickAction,
}, },
}, },
config_wayvr, config_wayvr,
graphics::{dmabuf::WGfxDmabuf, CommandBuffers, Vert2Uv}, graphics::{CommandBuffers, Vert2Uv, dmabuf::WGfxDmabuf},
state::{self, AppState}, state::{self, AppState},
subsystem::input::KeyboardFocus, subsystem::{hid::WheelDelta, input::KeyboardFocus},
windowing::{ windowing::{
backend::{ui_transform, FrameMeta, OverlayBackend, ShouldRender}, OverlayID, OverlaySelector, Z_ORDER_DASHBOARD,
backend::{FrameMeta, OverlayBackend, ShouldRender, ui_transform},
manager::OverlayWindowManager, manager::OverlayWindowManager,
window::{OverlayWindowConfig, OverlayWindowData, OverlayWindowState}, window::{OverlayWindowConfig, OverlayWindowData, OverlayWindowState},
OverlayID, OverlaySelector, Z_ORDER_DASHBOARD,
}, },
}; };
@@ -770,15 +769,10 @@ impl OverlayBackend for WayVRBackend {
&mut self, &mut self,
_app: &mut state::AppState, _app: &mut state::AppState,
_hit: &input::PointerHit, _hit: &input::PointerHit,
delta_y: f32, delta: WheelDelta,
delta_x: f32,
) { ) {
let ctx = self.context.borrow(); let ctx = self.context.borrow();
ctx.wayvr ctx.wayvr.borrow_mut().data.state.send_mouse_scroll(delta);
.borrow_mut()
.data
.state
.send_mouse_scroll(delta_y, delta_x);
} }
fn get_interaction_transform(&mut self) -> Option<Affine2> { fn get_interaction_transform(&mut self) -> Option<Affine2> {

View File

@@ -3,6 +3,17 @@
# Default: 300 # Default: 300
click_freeze_time_ms: 300 click_freeze_time_ms: 300
# Make scroll events inverted in X/Y axis
# Default: false
invert_scroll_direction_x: false
invert_scroll_direction_y: false
# Change speed of scrolling
# Default: 1.0
# 0.5: half the speed
# 2.0: twice the speed
scroll_speed: 1.0
# Default: true # Default: true
keyboard_sound_enabled: true keyboard_sound_enabled: true

View File

@@ -1,5 +1,5 @@
use glam::{IVec2, Vec2}; use glam::Vec2;
use idmap::{idmap, IdMap}; use idmap::{IdMap, idmap};
use idmap_derive::IntegerId; use idmap_derive::IntegerId;
use input_linux::{ use input_linux::{
AbsoluteAxis, AbsoluteInfo, AbsoluteInfoSetup, EventKind, InputId, Key, RelativeAxis, AbsoluteAxis, AbsoluteInfo, AbsoluteInfoSetup, EventKind, InputId, Key, RelativeAxis,
@@ -40,10 +40,15 @@ pub(super) fn initialize() -> Box<dyn HidProvider> {
Box::new(DummyProvider {}) Box::new(DummyProvider {})
} }
pub struct WheelDelta {
pub x: f32,
pub y: f32,
}
pub trait HidProvider: Sync + Send { pub trait HidProvider: Sync + Send {
fn mouse_move(&mut self, pos: Vec2); fn mouse_move(&mut self, pos: Vec2);
fn send_button(&mut self, button: u16, down: bool); fn send_button(&mut self, button: u16, down: bool);
fn wheel(&mut self, delta_y: i32, delta_x: i32); fn wheel(&mut self, delta: WheelDelta);
fn set_modifiers(&mut self, mods: u8); fn set_modifiers(&mut self, mods: u8);
fn send_key(&self, key: VirtualKey, down: bool); fn send_key(&self, key: VirtualKey, down: bool);
fn set_desktop_extent(&mut self, extent: Vec2); fn set_desktop_extent(&mut self, extent: Vec2);
@@ -61,7 +66,7 @@ struct MouseAction {
last_requested_pos: Option<Vec2>, last_requested_pos: Option<Vec2>,
pos: Option<Vec2>, pos: Option<Vec2>,
button: Option<MouseButtonAction>, button: Option<MouseButtonAction>,
scroll: Option<IVec2>, scroll: Option<WheelDelta>,
} }
pub struct UInputProvider { pub struct UInputProvider {
@@ -195,7 +200,12 @@ impl UInputProvider {
log::error!("{res}"); log::error!("{res}");
} }
} }
fn wheel_internal(&self, delta_y: i32, delta_x: i32) {
fn wheel_internal(&self, delta: WheelDelta) {
let multiplier = 64.0; /* cherry-picked value, overall scrolling speed can be altered via `scroll_speed` in the config */
let delta_x = (delta.x * multiplier) as i32;
let delta_y = (delta.y * multiplier) as i32;
let time = get_time(); let time = get_time();
let events = [ let events = [
new_event(time, EV_REL, RelativeAxis::WheelHiRes as _, delta_y), new_event(time, EV_REL, RelativeAxis::WheelHiRes as _, delta_y),
@@ -257,14 +267,16 @@ impl HidProvider for UInputProvider {
self.current_action.pos = self.current_action.last_requested_pos; self.current_action.pos = self.current_action.last_requested_pos;
} }
} }
fn wheel(&mut self, delta_y: i32, delta_x: i32) {
fn wheel(&mut self, delta: WheelDelta) {
if self.current_action.scroll.is_none() { if self.current_action.scroll.is_none() {
self.current_action.scroll = Some(IVec2::new(delta_x, delta_y)); self.current_action.scroll = Some(delta);
// Pass mouse motion events only if not scrolling // Pass mouse motion events only if not scrolling
// (allows scrolling on all Chromium-based applications) // (allows scrolling on all Chromium-based applications)
self.current_action.pos = None; self.current_action.pos = None;
} }
} }
fn commit(&mut self) { fn commit(&mut self) {
if let Some(pos) = self.current_action.pos.take() { if let Some(pos) = self.current_action.pos.take() {
self.mouse_move_internal(pos); self.mouse_move_internal(pos);
@@ -273,7 +285,7 @@ impl HidProvider for UInputProvider {
self.send_button_internal(button.button, button.down); self.send_button_internal(button.button, button.down);
} }
if let Some(scroll) = self.current_action.scroll.take() { if let Some(scroll) = self.current_action.scroll.take() {
self.wheel_internal(scroll.y, scroll.x); self.wheel_internal(scroll);
} }
} }
} }
@@ -281,7 +293,7 @@ impl HidProvider for UInputProvider {
impl HidProvider for DummyProvider { impl HidProvider for DummyProvider {
fn mouse_move(&mut self, _pos: Vec2) {} fn mouse_move(&mut self, _pos: Vec2) {}
fn send_button(&mut self, _button: u16, _down: bool) {} fn send_button(&mut self, _button: u16, _down: bool) {}
fn wheel(&mut self, _delta_y: i32, _delta_x: i32) {} fn wheel(&mut self, _delta: WheelDelta) {}
fn set_modifiers(&mut self, _modifiers: u8) {} fn set_modifiers(&mut self, _modifiers: u8) {}
fn send_key(&self, _key: VirtualKey, _down: bool) {} fn send_key(&self, _key: VirtualKey, _down: bool) {}
fn set_desktop_extent(&mut self, _extent: Vec2) {} fn set_desktop_extent(&mut self, _extent: Vec2) {}

View File

@@ -6,6 +6,7 @@ use crate::{
backend::input::{HoverResult, PointerHit}, backend::input::{HoverResult, PointerHit},
graphics::CommandBuffers, graphics::CommandBuffers,
state::AppState, state::AppState,
subsystem::hid::WheelDelta,
}; };
#[derive(Default, Clone, Copy)] #[derive(Default, Clone, Copy)]
@@ -51,7 +52,7 @@ pub trait OverlayBackend {
fn on_hover(&mut self, app: &mut AppState, hit: &PointerHit) -> HoverResult; fn on_hover(&mut self, app: &mut AppState, hit: &PointerHit) -> HoverResult;
fn on_left(&mut self, app: &mut AppState, pointer: usize); fn on_left(&mut self, app: &mut AppState, pointer: usize);
fn on_pointer(&mut self, app: &mut AppState, hit: &PointerHit, pressed: bool); fn on_pointer(&mut self, app: &mut AppState, hit: &PointerHit, pressed: bool);
fn on_scroll(&mut self, app: &mut AppState, hit: &PointerHit, delta_y: f32, delta_x: f32); fn on_scroll(&mut self, app: &mut AppState, hit: &PointerHit, delta: WheelDelta);
fn get_interaction_transform(&mut self) -> Option<Affine2>; fn get_interaction_transform(&mut self) -> Option<Affine2>;
} }