diff --git a/wayvr/src/backend/wayvr/client.rs b/wayvr/src/backend/wayvr/client.rs index 7f20e582..72fd9aa7 100644 --- a/wayvr/src/backend/wayvr/client.rs +++ b/wayvr/src/backend/wayvr/client.rs @@ -9,10 +9,10 @@ use std::{ use anyhow::Context; use glam::Vec2; use smithay::{ - backend::input::{ButtonState, Keycode}, + backend::input::{Axis, AxisSource, ButtonState, Keycode}, input::{ keyboard::KeyboardHandle, - pointer::{ButtonEvent, MotionEvent, PointerHandle}, + pointer::{AxisFrame, ButtonEvent, MotionEvent, PointerHandle}, }, reexports::wayland_server::{self, Resource, protocol::wl_surface::WlSurface}, utils::{Logical, Point, SerialCounter}, @@ -320,6 +320,34 @@ impl WayVRCompositor { self.seat_pointer.frame(&mut self.state); } + pub fn send_pointer_axis_wheel(&mut self, delta: super::WheelDelta) { + let time = super::time::get_millis() as u32; + + let multiplier = 64.0; // stolen from uniput.rs + let delta_x = (delta.x * multiplier) as i32; + let delta_y = (delta.y * multiplier) as i32; + + if delta_x == 0 && delta_y == 0 { + return; + } + + let mut frame = AxisFrame::new(time).source(AxisSource::Wheel); + + if delta_x != 0 { + frame = frame + .value(Axis::Horizontal, delta_x as f64 * 15.0) + .v120(Axis::Horizontal, delta_x * 120); + } + + if delta_y != 0 { + frame = frame + .value(Axis::Vertical, delta_y as f64 * 15.0) + .v120(Axis::Vertical, delta_y * 120); + } + + self.seat_pointer.axis(&mut self.state, frame); + self.seat_pointer.frame(&mut self.state); + } } const STARTING_WAYLAND_ADDR_IDX: u32 = 20; diff --git a/wayvr/src/backend/wayvr/mod.rs b/wayvr/src/backend/wayvr/mod.rs index 37082115..d192f8e9 100644 --- a/wayvr/src/backend/wayvr/mod.rs +++ b/wayvr/src/backend/wayvr/mod.rs @@ -643,7 +643,7 @@ impl WvrServerState { self.manager.send_pointer_button(index, pressed); } - pub fn send_mouse_button_main_surface( + pub fn send_mouse_button_to_toplevel( &mut self, click_freeze: i32, hover_window: window::WindowHandle, @@ -666,6 +666,48 @@ impl WvrServerState { self.manager.send_pointer_button(index, pressed); } + pub fn send_mouse_scroll_to_surface( + &mut self, + surface: WlSurface, + global_pos: Vec2, + surface_origin: Vec2, + hover_window: window::WindowHandle, + delta: WheelDelta, + ) { + // Do not respect mouse_freeze here. A scroll event should still update focus. + self.manager + .send_mouse_move_to_surface(surface, global_pos, surface_origin); + + self.wm.mouse = Some(window::MouseState { + hover_window, + x: global_pos.x.max(0.0) as u32, + y: global_pos.y.max(0.0) as u32, + }); + + self.manager.send_pointer_axis_wheel(delta); + } + + pub fn send_mouse_scroll_to_toplevel( + &mut self, + handle: window::WindowHandle, + pos: Vec2, + delta: WheelDelta, + ) { + if let Some(window) = self.wm.windows.get_mut(&handle) { + window.send_mouse_move(&mut self.manager, pos.x as u32, pos.y as u32); + } else { + return; + } + + self.wm.mouse = Some(window::MouseState { + hover_window: handle, + x: pos.x.max(0.0) as u32, + y: pos.y.max(0.0) as u32, + }); + + self.manager.send_pointer_axis_wheel(delta); + } + pub fn send_mouse_move(&mut self, handle: window::WindowHandle, x: u32, y: u32) { if self.mouse_freeze > Instant::now() { return; @@ -700,10 +742,6 @@ impl WvrServerState { Window::send_mouse_up(&mut self.manager, index); } - pub fn send_mouse_scroll(&mut self, delta: WheelDelta) { - Window::send_mouse_scroll(&mut self.manager, delta); - } - pub fn send_key(&mut self, virtual_key: u32, down: bool) { self.manager.send_key(virtual_key, down); } diff --git a/wayvr/src/overlays/wayvr.rs b/wayvr/src/overlays/wayvr.rs index 050e9703..b13bb6e6 100644 --- a/wayvr/src/overlays/wayvr.rs +++ b/wayvr/src/overlays/wayvr.rs @@ -784,7 +784,7 @@ impl OverlayBackend for WvrWindowBackend { app.wvr_server .as_mut() .unwrap() - .send_mouse_button_main_surface( + .send_mouse_button_to_toplevel( click_freeze, self.window, outside_pos, @@ -812,7 +812,7 @@ impl OverlayBackend for WvrWindowBackend { app.wvr_server .as_mut() .unwrap() - .send_mouse_button_main_surface( + .send_mouse_button_to_toplevel( click_freeze, self.window, outside_pos, @@ -868,14 +868,40 @@ impl OverlayBackend for WvrWindowBackend { } } - fn on_scroll( - &mut self, - app: &mut state::AppState, - _hit: &input::PointerHit, - delta: WheelDelta, - ) { - let wvr_server = app.wvr_server.as_mut().unwrap(); //never None - wvr_server.send_mouse_scroll(delta); + fn on_scroll(&mut self, app: &mut state::AppState, hit: &input::PointerHit, delta: WheelDelta) { + let target = self.hit_target(hit); + + match target { + Some(WvrHitTarget::Panel(hit2)) => { + self.panel.on_scroll(app, &hit2, delta); + let _ = hit2; + } + + Some(WvrHitTarget::Popup { + surface, + global_pos, + surface_origin, + }) + | Some(WvrHitTarget::Surface { + surface, + global_pos, + surface_origin, + }) => { + let wvr_server = app.wvr_server.as_mut().unwrap(); + wvr_server.send_mouse_scroll_to_surface( + surface, + global_pos, + surface_origin, + self.window, + delta, + ); + } + Some(WvrHitTarget::Toplevel { pos }) => { + let wvr_server = app.wvr_server.as_mut().unwrap(); + wvr_server.send_mouse_scroll_to_toplevel(self.window, pos, delta); + } + None => {} + } } fn get_interaction_transform(&mut self) -> Option {