From 8f09a13917e4309074c884285bdf422c44762433 Mon Sep 17 00:00:00 2001 From: galister <22305755+galister@users.noreply.github.com> Date: Sat, 4 Jul 2026 21:34:53 +0900 Subject: [PATCH] fix xdg-decoration + add wl-viewporter --- wayvr/src/backend/wayvr/comp.rs | 10 ++++---- wayvr/src/overlays/wayvr.rs | 42 +++++++++++++++++++++++++++------ 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/wayvr/src/backend/wayvr/comp.rs b/wayvr/src/backend/wayvr/comp.rs index 2b52cb4c..daa3f95b 100644 --- a/wayvr/src/backend/wayvr/comp.rs +++ b/wayvr/src/backend/wayvr/comp.rs @@ -28,14 +28,14 @@ use smithay::wayland::selection::{ wlr_data_control as selection_wlr, }; use smithay::wayland::shell::kde::decoration::{KdeDecorationHandler, KdeDecorationState}; -use smithay::wayland::shell::xdg::decoration::XdgDecorationHandler; +use smithay::wayland::shell::xdg::decoration::{XdgDecorationHandler, XdgDecorationState}; use smithay::wayland::shm::{ShmHandler, ShmState, with_buffer_contents}; use smithay::wayland::single_pixel_buffer::get_single_pixel_buffer; use smithay::{ delegate_compositor, delegate_data_control, delegate_data_device, delegate_dmabuf, delegate_ext_data_control, delegate_kde_decoration, delegate_output, delegate_primary_selection, delegate_seat, delegate_shm, delegate_single_pixel_buffer, - delegate_xdg_decoration, delegate_xdg_shell, + delegate_viewporter, delegate_xdg_decoration, delegate_xdg_shell, }; use std::collections::{HashMap, HashSet}; use std::fs::File; @@ -77,6 +77,7 @@ pub struct Application { pub primary_selection_state: PrimarySelectionState, pub ext_data_control_state: selection_ext::DataControlState, pub wlr_data_control_state: selection_wlr::DataControlState, + pub xdg_decoration_state: XdgDecorationState, pub kde_decoration_state: KdeDecorationState, pub wayvr_tasks: SyncEventQueue, pub popup_manager: PopupManager, @@ -163,10 +164,6 @@ impl Application { pub fn take_redraw_request(&mut self, surface_id: &ObjectId) -> bool { self.redraw_requests.remove(surface_id) } - - pub fn has_redraw_request(&self, surface_id: &ObjectId) -> bool { - self.redraw_requests.contains(surface_id) - } } impl compositor::CompositorHandler for Application { @@ -604,6 +601,7 @@ impl KdeDecorationHandler for Application { delegate_dmabuf!(Application); delegate_xdg_shell!(Application); delegate_compositor!(Application); +delegate_viewporter!(Application); delegate_shm!(Application); delegate_seat!(Application); delegate_data_device!(Application); diff --git a/wayvr/src/overlays/wayvr.rs b/wayvr/src/overlays/wayvr.rs index dc238ff1..050e9703 100644 --- a/wayvr/src/overlays/wayvr.rs +++ b/wayvr/src/overlays/wayvr.rs @@ -5,7 +5,8 @@ use smithay::{ utils::{Logical, Point}, wayland::{ compositor::{ - SubsurfaceCachedState, TraversalAction, with_states, with_surface_tree_upward, + SUBSURFACE_ROLE, SubsurfaceCachedState, SurfaceAttributes, TraversalAction, + with_states, with_surface_tree_upward, }, shell::xdg::XdgPopupSurfaceData, }, @@ -367,11 +368,11 @@ impl WvrWindowBackend { return self.panel_hit_from_hit(hit).map(WvrHitTarget::Panel); } - let hit_surface = self.surfaces.iter().rev().find(|s| { - let local = client_pos - s.pos; - - local.x >= 0.0 && local.y >= 0.0 && local.x < s.size.x && local.y < s.size.y - }); + let hit_surface = self + .surfaces + .iter() + .rev() + .find(|s| surface_accepts_input(s, client_pos)); if let Some(surface) = hit_surface { return Some(WvrHitTarget::Surface { @@ -939,7 +940,7 @@ fn rendered_surfaces_dirty(old: &[RenderedSurface], new: &[RenderedSurface]) -> } fn surface_location(states: &smithay::wayland::compositor::SurfaceData) -> Point { - if states.role == Some("wl_subsurface") { + if states.role == Some(SUBSURFACE_ROLE) { let mut guard = states.cached_state.get::(); guard.current().location } else { @@ -949,6 +950,7 @@ fn surface_location(states: &smithay::wayland::compositor::SurfaceData) -> Point fn collect_rendered_surface_tree(root: &WlSurface) -> Vec { let mut out = Vec::new(); + let root_id = root.id(); with_surface_tree_upward( root, @@ -960,6 +962,10 @@ fn collect_rendered_surface_tree(root: &WlSurface) -> Vec { TraversalAction::DoChildren(pos) }, |surface, states, parent_pos| { + if surface.id() == root_id { + return; + } + let pos = *parent_pos + surface_location(states); if let Some(surf) = SurfaceBufWithImage::get_from_surface(states) { @@ -981,3 +987,25 @@ fn collect_rendered_surface_tree(root: &WlSurface) -> Vec { out } + +fn surface_accepts_input(surface: &RenderedSurface, global_pos: Vec2) -> bool { + let local = global_pos - surface.pos; + + if local.x < 0.0 || local.y < 0.0 || local.x >= surface.size.x || local.y >= surface.size.y { + return false; + } + + with_states(&surface.surface, |states| { + let mut guard = states.cached_state.get::(); + let attrs = guard.current(); + + match attrs.input_region.as_ref() { + None => true, + Some(region) => { + let point = + Point::::from((local.x.floor() as i32, local.y.floor() as i32)); + region.contains(point) + } + } + }) +}