diff --git a/wayvr/src/backend/input.rs b/wayvr/src/backend/input.rs index d6c69992..8a71c674 100644 --- a/wayvr/src/backend/input.rs +++ b/wayvr/src/backend/input.rs @@ -32,6 +32,15 @@ pub struct HoverResult { pub consume: bool, } +impl HoverResult { + pub fn consume() -> Self { + HoverResult { + consume: true, + ..Default::default() + } + } +} + pub struct TrackedDevice { pub soc: Option, pub charging: bool, diff --git a/wayvr/src/backend/wayvr/client.rs b/wayvr/src/backend/wayvr/client.rs index a04d7ef2..1719e39e 100644 --- a/wayvr/src/backend/wayvr/client.rs +++ b/wayvr/src/backend/wayvr/client.rs @@ -14,7 +14,7 @@ use smithay::{ keyboard::KeyboardHandle, pointer::{AxisFrame, ButtonEvent, MotionEvent, PointerHandle}, }, - reexports::wayland_server::{self, Resource, protocol::wl_surface::WlSurface}, + reexports::wayland_server::{self, protocol::wl_surface::WlSurface}, utils::{Logical, Point, SerialCounter}, }; use wgui::log::LogErr; @@ -247,12 +247,18 @@ impl WayVRCompositor { .context("Failed to set keymap") } - pub fn send_mouse_move_unfocused(&mut self, global_pos: Vec2) { + pub fn send_mouse_move(&mut self, focus: Option<(WlSurface, Vec2)>, global_pos: Vec2) { let location: Point = (global_pos.x as f64, global_pos.y as f64).into(); + let focus = focus.map(|(surface, origin)| { + let focus_location: Point = (origin.x as f64, origin.y as f64).into(); + + (surface, focus_location) + }); + self.seat_pointer.motion( &mut self.state, - None, + focus, &MotionEvent { location, serial: self.serial_counter.next_serial(), @@ -263,33 +269,6 @@ impl WayVRCompositor { self.seat_pointer.frame(&mut self.state); } - pub fn send_mouse_move_to_surface( - &mut self, - surface: WlSurface, - global_pos: Vec2, - surface_origin: Vec2, - ) { - let location: Point = (global_pos.x as f64, global_pos.y as f64).into(); - - let focus_location: Point = - (surface_origin.x as f64, surface_origin.y as f64).into(); - - let serial = self.serial_counter.next_serial(); - let time = super::time::get_millis() as u32; - - self.seat_pointer.motion( - &mut self.state, - Some((surface, focus_location)), - &MotionEvent { - location, - serial, - time, - }, - ); - - self.seat_pointer.frame(&mut self.state); - } - pub fn send_pointer_button(&mut self, index: super::MouseIndex, pressed: bool) { let state = if pressed { ButtonState::Pressed @@ -305,11 +284,6 @@ impl WayVRCompositor { super::MouseIndex::Right => 0x111, }; - log::trace!( - "pointer button: button={button:#x} pressed={pressed} focus={:?}", - self.seat_pointer.current_focus().map(|s| s.id()) - ); - self.seat_pointer.button( &mut self.state, &ButtonEvent { diff --git a/wayvr/src/backend/wayvr/mod.rs b/wayvr/src/backend/wayvr/mod.rs index 502916cc..fb489f80 100644 --- a/wayvr/src/backend/wayvr/mod.rs +++ b/wayvr/src/backend/wayvr/mod.rs @@ -63,7 +63,6 @@ use crate::{ wayvr::{ image_importer::ImageImporter, process::{KillSignal, Process}, - window::Window, }, }, graphics::WGfxExtras, @@ -135,6 +134,12 @@ pub enum MouseIndex { Right, } +pub enum PointerFocusTarget { + Surface { surface: WlSurface, origin: Vec2 }, + Toplevel, + None, +} + pub enum TickTask { NewExternalProcess(ExternalProcessRequest), // Call WayVRCompositor::add_client after receiving this message } @@ -644,19 +649,31 @@ impl WvrServerState { self.manager.seat_pointer.is_grabbed() } - pub fn send_mouse_move_to_surface( + pub fn send_mouse_move( &mut self, - surface: WlSurface, + target: PointerFocusTarget, global_pos: Vec2, - surface_origin: Vec2, hover_window: window::WindowHandle, ) { if self.mouse_freeze > Instant::now() { return; } - self.manager - .send_mouse_move_to_surface(surface, global_pos, surface_origin); + let focus = match target { + PointerFocusTarget::Surface { surface, origin } => Some((surface, origin)), + PointerFocusTarget::Toplevel => { + let surface = self + .wm + .windows + .get(&hover_window) + .map(|x| x.toplevel.wl_surface().clone()); + + surface.clone().map(|surface| (surface, Vec2::ZERO)) + } + PointerFocusTarget::None => None, + }; + + self.manager.send_mouse_move(focus, global_pos); self.mouse_freeze = Instant::now() + Duration::from_millis(1); @@ -667,40 +684,52 @@ impl WvrServerState { }); } - pub fn send_mouse_button_to_surface( + pub fn send_mouse_button( &mut self, - surface: WlSurface, + target: PointerFocusTarget, global_pos: Vec2, - surface_origin: Vec2, hover_window: window::WindowHandle, index: MouseIndex, pressed: bool, - ) { - self.manager - .send_mouse_move_to_surface(surface, global_pos, surface_origin); - - self.wm.mouse = Some(window::MouseState { - hover_window, - x: global_pos.x as u32, - y: global_pos.y as u32, - }); - - self.manager.send_pointer_button(index, pressed); - } - - pub fn send_mouse_button_to_toplevel( - &mut self, click_freeze: i32, - hover_window: window::WindowHandle, - global_pos: Vec2, - index: MouseIndex, - pressed: bool, ) { if pressed { self.mouse_freeze = Instant::now() + Duration::from_millis(click_freeze.max(0) as u64); } - self.manager.send_mouse_move_unfocused(global_pos); + let (focus, focus_keyboard) = match target { + PointerFocusTarget::Surface { surface, origin } => (Some((surface, origin)), None), + PointerFocusTarget::Toplevel => { + let surface = self + .wm + .windows + .get(&hover_window) + .map(|x| x.toplevel.wl_surface().clone()); + + ( + surface.clone().map(|surface| (surface, Vec2::ZERO)), + pressed.then_some(surface).flatten(), + ) + } + PointerFocusTarget::None => { + let surface = self + .wm + .windows + .get(&hover_window) + .map(|x| x.toplevel.wl_surface().clone()); + (None, pressed.then_some(surface).flatten()) + } + }; + + if focus_keyboard.is_some() { + self.manager.seat_keyboard.set_focus( + &mut self.manager.state, + focus_keyboard, + self.manager.serial_counter.next_serial(), + ); + } + + self.manager.send_mouse_move(focus, global_pos); self.wm.mouse = Some(window::MouseState { hover_window, @@ -711,10 +740,10 @@ impl WvrServerState { self.manager.send_pointer_button(index, pressed); } - pub fn send_mouse_scroll_to_surface( + pub fn send_mouse_scroll( &mut self, - global_pos: Vec2, hover_window: window::WindowHandle, + global_pos: Vec2, delta: WheelDelta, ) { self.wm.mouse = Some(window::MouseState { @@ -726,55 +755,6 @@ impl WvrServerState { self.manager.send_pointer_axis_wheel(delta); } - pub fn send_mouse_scroll_to_toplevel( - &mut self, - handle: window::WindowHandle, - pos: Vec2, - delta: WheelDelta, - ) { - 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; - } - if let Some(window) = self.wm.windows.get_mut(&handle) { - window.send_mouse_move(&mut self.manager, x, y); - } else { - return; - } - self.mouse_freeze = Instant::now() + Duration::from_millis(1); // prevent other pointer from moving the mouse on the same frame - self.wm.mouse = Some(window::MouseState { - hover_window: handle, - x, - y, - }); - } - - pub fn send_mouse_down( - &mut self, - click_freeze: i32, - handle: window::WindowHandle, - index: MouseIndex, - ) { - self.mouse_freeze = Instant::now() + Duration::from_millis(click_freeze as _); - - if let Some(window) = self.wm.windows.get_mut(&handle) { - window.send_mouse_down(&mut self.manager, index); - } - } - - pub fn send_mouse_up(&mut self, index: MouseIndex) { - Window::send_mouse_up(&mut self.manager, index); - } - pub fn send_key(&mut self, virtual_key: u32, down: bool) { self.manager.send_key(virtual_key, down); } diff --git a/wayvr/src/backend/wayvr/window.rs b/wayvr/src/backend/wayvr/window.rs index fff4d14d..dc40149c 100644 --- a/wayvr/src/backend/wayvr/window.rs +++ b/wayvr/src/backend/wayvr/window.rs @@ -1,16 +1,9 @@ use std::rc::Rc; -use smithay::{ - input, - utils::{Logical, Point}, - wayland::shell::xdg::ToplevelSurface, -}; +use smithay::wayland::shell::xdg::ToplevelSurface; use wayvr_ipc::packet_server; -use crate::{ - backend::wayvr::{client::WayVRCompositor, process}, - gen_id, -}; +use crate::{backend::wayvr::process, gen_id}; #[derive(Debug)] pub struct Window { @@ -42,72 +35,6 @@ impl Window { self.size_x = size_x; self.size_y = size_y; } - - pub(super) fn send_mouse_move(&self, manager: &mut WayVRCompositor, x: u32, y: u32) { - let surf = self.toplevel.wl_surface().clone(); - let point = Point::::from((f64::from(x as i32), f64::from(y as i32))); - - manager.seat_pointer.motion( - &mut manager.state, - Some((surf, Point::from((0.0, 0.0)))), - &input::pointer::MotionEvent { - serial: manager.serial_counter.next_serial(), - time: 0, - location: point, - }, - ); - - manager.seat_pointer.frame(&mut manager.state); - } - - const fn get_mouse_index_number(index: super::MouseIndex) -> u32 { - match index { - super::MouseIndex::Left => 0x110, /* BTN_LEFT */ - super::MouseIndex::Center => 0x112, /* BTN_MIDDLE */ - super::MouseIndex::Right => 0x111, /* BTN_RIGHT */ - } - } - - pub(super) fn send_mouse_down( - &mut self, - manager: &mut WayVRCompositor, - index: super::MouseIndex, - ) { - let surf = self.toplevel.wl_surface().clone(); - - // Change keyboard focus to pressed window - manager.seat_keyboard.set_focus( - &mut manager.state, - Some(surf), - manager.serial_counter.next_serial(), - ); - - manager.seat_pointer.button( - &mut manager.state, - &input::pointer::ButtonEvent { - button: Self::get_mouse_index_number(index), - serial: manager.serial_counter.next_serial(), - time: 0, - state: smithay::backend::input::ButtonState::Pressed, - }, - ); - - manager.seat_pointer.frame(&mut manager.state); - } - - pub(super) fn send_mouse_up(manager: &mut WayVRCompositor, index: super::MouseIndex) { - manager.seat_pointer.button( - &mut manager.state, - &input::pointer::ButtonEvent { - button: Self::get_mouse_index_number(index), - serial: manager.serial_counter.next_serial(), - time: 0, - state: smithay::backend::input::ButtonState::Released, - }, - ); - - manager.seat_pointer.frame(&mut manager.state); - } } #[derive(Debug)] diff --git a/wayvr/src/overlays/screen/backend.rs b/wayvr/src/overlays/screen/backend.rs index 8b78a7db..ec049f28 100644 --- a/wayvr/src/overlays/screen/backend.rs +++ b/wayvr/src/overlays/screen/backend.rs @@ -313,10 +313,7 @@ impl OverlayBackend for ScreenBackend { app.hid_provider.inner.mouse_move(pos); set_next_move(app.session.config.mouse_move_interval_ms as _); } - HoverResult { - consume: true, - ..HoverResult::default() - } + HoverResult::consume() } fn on_pointer(&mut self, app: &mut AppState, hit: &PointerHit, pressed: bool) { let mut btn = match hit.mode { diff --git a/wayvr/src/overlays/screen/mirror.rs b/wayvr/src/overlays/screen/mirror.rs index 0feabf8a..a7017ac3 100644 --- a/wayvr/src/overlays/screen/mirror.rs +++ b/wayvr/src/overlays/screen/mirror.rs @@ -162,10 +162,7 @@ impl OverlayBackend for MirrorBackend { } fn on_hover(&mut self, _: &mut AppState, _: &PointerHit) -> HoverResult { - HoverResult { - consume: true, - ..HoverResult::default() - } + HoverResult::consume() } fn on_left(&mut self, _: &mut AppState, _: usize) {} fn on_pointer(&mut self, _: &mut AppState, _: &PointerHit, _: bool) {} diff --git a/wayvr/src/overlays/wayvr.rs b/wayvr/src/overlays/wayvr.rs index 7c1cc28d..8ed7dd63 100644 --- a/wayvr/src/overlays/wayvr.rs +++ b/wayvr/src/overlays/wayvr.rs @@ -37,7 +37,10 @@ use crate::{ backend::{ XrBackend, input::{self, HoverResult}, - wayvr::{self, SurfaceBufWithImage, process::KillSignal, window::WindowHandle}, + wayvr::{ + self, PointerFocusTarget, SurfaceBufWithImage, process::KillSignal, + window::WindowHandle, + }, }, graphics::{ExtentExt, Vert2Uv, upload_quad_vertices}, gui::panel::{ @@ -131,12 +134,12 @@ enum WvrHitTarget { Surface { surface: WlSurface, global_pos: Vec2, - surface_origin: Vec2, + origin: Vec2, }, Popup { surface: WlSurface, global_pos: Vec2, - surface_origin: Vec2, + origin: Vec2, }, } @@ -358,7 +361,7 @@ impl WvrWindowBackend { return Some(WvrHitTarget::Popup { surface, global_pos: client_pos, - surface_origin, + origin: surface_origin, }); } @@ -376,7 +379,7 @@ impl WvrWindowBackend { return Some(WvrHitTarget::Surface { surface: surface.surface.clone(), global_pos: client_pos, - surface_origin: surface.pos, + origin: surface.pos, }); } @@ -491,8 +494,6 @@ impl OverlayBackend for WvrWindowBackend { continue; } - // Same logic you already use. `point` is the popup tree position; - // `geometry().loc` accounts for xdg_surface window geometry offset. let popup_origin = point - popup.geometry().loc; popup_roots.push(PopupRoot { @@ -716,10 +717,7 @@ impl OverlayBackend for WvrWindowBackend { fn on_hover(&mut self, app: &mut state::AppState, hit: &input::PointerHit) -> HoverResult { if std::mem::take(&mut self.scrolling) { // we scrolled on previous frame so don't send mouse move events in case the user wants to scroll on this frame as well - return HoverResult { - haptics: None, - consume: true, - }; + return HoverResult::consume(); } match self.hit_target(hit) { @@ -730,12 +728,12 @@ impl OverlayBackend for WvrWindowBackend { Some(WvrHitTarget::Popup { surface, global_pos, - surface_origin, + origin, }) | Some(WvrHitTarget::Surface { surface, global_pos, - surface_origin, + origin, }) => { if self.panel_hovered { self.panel.on_left(app, hit.pointer); @@ -743,18 +741,13 @@ impl OverlayBackend for WvrWindowBackend { } let wvr_server = app.wvr_server.as_mut().unwrap(); - - wvr_server.send_mouse_move_to_surface( - surface, + wvr_server.send_mouse_move( + PointerFocusTarget::Surface { surface, origin }, global_pos, - surface_origin, self.window, ); - HoverResult { - haptics: None, - consume: true, - } + HoverResult::consume() } Some(WvrHitTarget::Toplevel { pos }) => { if self.panel_hovered { @@ -763,15 +756,11 @@ impl OverlayBackend for WvrWindowBackend { } let wvr_server = app.wvr_server.as_mut().unwrap(); + wvr_server.send_mouse_move(PointerFocusTarget::Toplevel, pos, self.window); - wvr_server.send_mouse_move(self.window, pos.x as u32, pos.y as u32); - - HoverResult { - haptics: None, - consume: true, - } + HoverResult::consume() } - None => HoverResult::default(), + None => HoverResult::default(), // pass } } @@ -789,22 +778,20 @@ impl OverlayBackend for WvrWindowBackend { let target = self.hit_target(hit); let outside_pos = self.unclamped_client_pos_from_hit(hit); + let click_freeze = app.session.config.click_freeze_time_ms; // if the press was consumed to dismiss a popup, consume the matching release too. if !pressed && self.popup_outside_button == Some(index) { self.popup_outside_button = None; - let click_freeze = app.session.config.click_freeze_time_ms; - app.wvr_server - .as_mut() - .unwrap() - .send_mouse_button_to_toplevel( - click_freeze, - self.window, - outside_pos, - index, - false, - ); + app.wvr_server.as_mut().unwrap().send_mouse_button( + PointerFocusTarget::None, + outside_pos, + self.window, + index, + false, + click_freeze, + ); return; } @@ -823,16 +810,14 @@ impl OverlayBackend for WvrWindowBackend { } let click_freeze = app.session.config.click_freeze_time_ms; - app.wvr_server - .as_mut() - .unwrap() - .send_mouse_button_to_toplevel( - click_freeze, - self.window, - outside_pos, - index, - pressed, - ); + app.wvr_server.as_mut().unwrap().send_mouse_button( + PointerFocusTarget::None, + outside_pos, + self.window, + index, + pressed, + click_freeze, + ); return; } @@ -845,22 +830,22 @@ impl OverlayBackend for WvrWindowBackend { Some(WvrHitTarget::Popup { surface, global_pos, - surface_origin, + origin, }) | Some(WvrHitTarget::Surface { surface, global_pos, - surface_origin, + origin, }) => { let wvr_server = app.wvr_server.as_mut().unwrap(); - wvr_server.send_mouse_button_to_surface( - surface, + wvr_server.send_mouse_button( + PointerFocusTarget::Surface { surface, origin }, global_pos, - surface_origin, self.window, index, pressed, + click_freeze, ); } @@ -868,14 +853,14 @@ impl OverlayBackend for WvrWindowBackend { let click_freeze = app.session.config.click_freeze_time_ms; let wvr_server = app.wvr_server.as_mut().unwrap(); - // normal toplevel click path, only when no popup grab is active. - wvr_server.send_mouse_move(self.window, pos.x as u32, pos.y as u32); - - if pressed { - wvr_server.send_mouse_down(click_freeze, self.window, index); - } else { - wvr_server.send_mouse_up(index); - } + wvr_server.send_mouse_button( + PointerFocusTarget::Toplevel, + pos, + self.window, + index, + pressed, + click_freeze, + ); } None => {} @@ -895,11 +880,11 @@ impl OverlayBackend for WvrWindowBackend { Some(WvrHitTarget::Popup { global_pos, .. }) | Some(WvrHitTarget::Surface { global_pos, .. }) => { let wvr_server = app.wvr_server.as_mut().unwrap(); - wvr_server.send_mouse_scroll_to_surface(global_pos, self.window, delta); + wvr_server.send_mouse_scroll(self.window, global_pos, 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); + wvr_server.send_mouse_scroll(self.window, pos, delta); } None => {} }