diff --git a/src/desktop/layer.rs b/src/desktop/layer.rs index e2f0ed5..11ae791 100644 --- a/src/desktop/layer.rs +++ b/src/desktop/layer.rs @@ -3,7 +3,7 @@ use crate::{ desktop::{utils::*, PopupManager, Space}, utils::{user_data::UserDataMap, Logical, Point, Rectangle}, wayland::{ - compositor::with_states, + compositor::{with_states, with_surface_tree_downward, TraversalAction}, output::{Inner as OutputInner, Output}, shell::wlr_layer::{ Anchor, ExclusiveZone, KeyboardInteractivity, Layer as WlrLayer, LayerSurface as WlrLayerSurface, @@ -29,6 +29,8 @@ pub struct LayerMap { layers: IndexSet, output: Weak<(Mutex, wayland_server::UserDataMap)>, zone: Rectangle, + // surfaces for tracking enter and leave events + surfaces: Vec, logger: ::slog::Logger, } @@ -54,6 +56,7 @@ pub fn layer_map_for_output(o: &Output) -> RefMut<'_, LayerMap> { .map(|mode| mode.size.to_logical(o.current_scale())) .unwrap_or_else(|| (0, 0).into()), ), + surfaces: Vec::new(), logger: (*o.inner.0.lock().unwrap()) .log .new(slog::o!("smithay_module" => "layer_map")), @@ -94,6 +97,26 @@ impl LayerMap { let _ = layer.user_data().get::().take(); self.arrange(); } + if let (Some(output), Some(surface)) = (self.output(), layer.get_surface()) { + with_surface_tree_downward( + surface, + (), + |_, _, _| TraversalAction::DoChildren(()), + |wl_surface, _, _| { + if self.surfaces.contains(wl_surface) { + slog::trace!( + self.logger, + "surface ({:?}) leaving output {:?}", + wl_surface, + output.name() + ); + output.leave(wl_surface); + self.surfaces.retain(|s| s != wl_surface); + } + }, + |_, _, _| true, + ); + } } /// Return the area of this output, that is not exclusive to any [`LayerSurface`]s. @@ -173,6 +196,27 @@ impl LayerMap { continue; }; + let logger_ref = &self.logger; + let surfaces_ref = &mut self.surfaces; + with_surface_tree_downward( + surface, + (), + |_, _, _| TraversalAction::DoChildren(()), + |wl_surface, _, _| { + if !surfaces_ref.contains(wl_surface) { + slog::trace!( + logger_ref, + "surface ({:?}) entering output {:?}", + wl_surface, + output.name() + ); + output.enter(wl_surface); + surfaces_ref.push(wl_surface.clone()); + } + }, + |_, _, _| true, + ); + let data = with_states(surface, |states| { *states.cached_state.current::() }) @@ -267,7 +311,8 @@ impl LayerMap { /// This function needs to be called periodically (though not necessarily frequently) /// to be able cleanup internally used resources. pub fn cleanup(&mut self) { - self.layers.retain(|layer| layer.alive()) + self.layers.retain(|layer| layer.alive()); + self.surfaces.retain(|s| s.as_ref().is_alive()); } }