wvr_server: surface-aware mouse wheel handling

This commit is contained in:
galister 2026-07-05 00:24:51 +09:00
parent 7c0c699b9a
commit e38dec41be
3 changed files with 109 additions and 17 deletions

View File

@ -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;

View File

@ -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);
}

View File

@ -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<Affine2> {