From 98da5fe467358596556d02c11183ff3c5f0db4fe Mon Sep 17 00:00:00 2001 From: Victoria Brekenfeld Date: Wed, 19 Jan 2022 20:41:34 +0100 Subject: [PATCH] desktop: Refactor output_{enter, leave} into utils --- src/desktop/layer.rs | 22 +------- src/desktop/space/mod.rs | 119 ++++++++++----------------------------- src/desktop/utils.rs | 86 ++++++++++++++++++++++++++++ 3 files changed, 118 insertions(+), 109 deletions(-) diff --git a/src/desktop/layer.rs b/src/desktop/layer.rs index 11ae791..bf23a1f 100644 --- a/src/desktop/layer.rs +++ b/src/desktop/layer.rs @@ -103,16 +103,7 @@ impl LayerMap { (), |_, _, _| 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); - } + output_leave(&output, &mut self.surfaces, wl_surface, &self.logger); }, |_, _, _| true, ); @@ -203,16 +194,7 @@ impl LayerMap { (), |_, _, _| 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()); - } + output_enter(&output, surfaces_ref, wl_surface, logger_ref); }, |_, _, _| true, ); diff --git a/src/desktop/space/mod.rs b/src/desktop/space/mod.rs index ed45ad9..2f91365 100644 --- a/src/desktop/space/mod.rs +++ b/src/desktop/space/mod.rs @@ -2,23 +2,22 @@ //! rendering helpers to add custom elements or different clients to a space. use crate::{ - backend::renderer::{utils::SurfaceState, Frame, ImportAll, Renderer}, + backend::renderer::{Frame, ImportAll, Renderer}, desktop::{ layer::{layer_map_for_output, LayerSurface}, + popup::PopupManager, + utils::{output_leave, output_update}, window::Window, }, utils::{Logical, Point, Rectangle, Transform}, wayland::{ - compositor::{ - get_parent, is_sync_subsurface, with_surface_tree_downward, SubsurfaceCachedState, - TraversalAction, - }, + compositor::{get_parent, is_sync_subsurface}, output::Output, shell::wlr_layer::Layer as WlrLayer, }, }; use indexmap::{IndexMap, IndexSet}; -use std::{cell::RefCell, collections::VecDeque, fmt}; +use std::{collections::VecDeque, fmt}; use wayland_server::protocol::wl_surface::WlSurface; mod element; @@ -326,97 +325,39 @@ impl Space { // the output. if !output_geometry.overlaps(bbox) { if let Some(surface) = kind.get_surface() { - with_surface_tree_downward( - surface, - (), - |_, _, _| TraversalAction::DoChildren(()), - |wl_surface, _, _| { - if output_state.surfaces.contains(wl_surface) { - slog::trace!( - self.logger, - "surface ({:?}) leaving output {:?}", - wl_surface, - output.name() - ); - output.leave(wl_surface); - output_state.surfaces.retain(|s| s != wl_surface); - } - }, - |_, _, _| true, - ) + output_leave(output, &mut output_state.surfaces, surface, &self.logger); } continue; } if let Some(surface) = kind.get_surface() { - with_surface_tree_downward( + output_update( + output, + output_geometry, + &mut output_state.surfaces, surface, window_loc(window, &self.id), - |_, states, location| { - let mut location = *location; - let data = states.data_map.get::>(); + &self.logger, + ); - if data.is_some() { - if states.role == Some("subsurface") { - let current = states.cached_state.current::(); - location += current.location; - } - - TraversalAction::DoChildren(location) - } else { - // If the parent surface is unmapped, then the child surfaces are hidden as - // well, no need to consider them here. - TraversalAction::SkipChildren - } - }, - |wl_surface, states, &loc| { - let data = states.data_map.get::>(); - - if let Some(size) = data.and_then(|d| d.borrow().surface_size()) { - let surface_rectangle = Rectangle { loc, size }; - - if output_geometry.overlaps(surface_rectangle) { - // We found a matching output, check if we already sent enter - if !output_state.surfaces.contains(wl_surface) { - slog::trace!( - self.logger, - "surface ({:?}) entering output {:?}", - wl_surface, - output.name() - ); - output.enter(wl_surface); - output_state.surfaces.push(wl_surface.clone()); - } - } else { - // Surface does not match output, if we sent enter earlier - // we should now send leave - if output_state.surfaces.contains(wl_surface) { - slog::trace!( - self.logger, - "surface ({:?}) leaving output {:?}", - wl_surface, - output.name() - ); - output.leave(wl_surface); - output_state.surfaces.retain(|s| s != wl_surface); - } - } - } else { - // Maybe the the surface got unmapped, send leave on output - if output_state.surfaces.contains(wl_surface) { - slog::trace!( - self.logger, - "surface ({:?}) leaving output {:?}", - wl_surface, - output.name() - ); - output.leave(wl_surface); - output_state.surfaces.retain(|s| s != wl_surface); - } - } - }, - |_, _, _| true, - ) + for (popup, location) in PopupManager::popups_for_surface(surface) + .ok() + .into_iter() + .flatten() + { + if let Some(surface) = popup.get_surface() { + let location = window_loc(window, &self.id) + window.geometry().loc + location + - popup.geometry().loc; + output_update( + output, + output_geometry, + &mut output_state.surfaces, + surface, + location, + &self.logger, + ); + } + } } } } diff --git a/src/desktop/utils.rs b/src/desktop/utils.rs index b855691..c726633 100644 --- a/src/desktop/utils.rs +++ b/src/desktop/utils.rs @@ -231,3 +231,89 @@ pub fn send_frames_surface_tree(surface: &wl_surface::WlSurface, time: u32) { |_, _, &()| true, ); } + +pub(crate) fn output_update( + output: &Output, + output_geometry: Rectangle, + surface_list: &mut Vec, + surface: &wl_surface::WlSurface, + location: Point, + logger: &slog::Logger, +) { + with_surface_tree_downward( + surface, + location, + |_, states, location| { + let mut location = *location; + let data = states.data_map.get::>(); + + if data.is_some() { + if states.role == Some("subsurface") { + let current = states.cached_state.current::(); + location += current.location; + } + + TraversalAction::DoChildren(location) + } else { + // If the parent surface is unmapped, then the child surfaces are hidden as + // well, no need to consider them here. + TraversalAction::SkipChildren + } + }, + |wl_surface, states, &loc| { + let data = states.data_map.get::>(); + + if let Some(size) = data.and_then(|d| d.borrow().surface_size()) { + let surface_rectangle = Rectangle { loc, size }; + if output_geometry.overlaps(surface_rectangle) { + // We found a matching output, check if we already sent enter + output_enter(output, surface_list, wl_surface, logger); + } else { + // Surface does not match output, if we sent enter earlier + // we should now send leave + output_leave(output, surface_list, wl_surface, logger); + } + } else { + // Maybe the the surface got unmapped, send leave on output + output_leave(output, surface_list, wl_surface, logger); + } + }, + |_, _, _| true, + ); +} + +pub(crate) fn output_enter( + output: &Output, + surface_list: &mut Vec, + surface: &wl_surface::WlSurface, + logger: &slog::Logger, +) { + if !surface_list.contains(surface) { + slog::debug!( + logger, + "surface ({:?}) entering output {:?}", + surface, + output.name() + ); + output.enter(surface); + surface_list.push(surface.clone()); + } +} + +pub(crate) fn output_leave( + output: &Output, + surface_list: &mut Vec, + surface: &wl_surface::WlSurface, + logger: &slog::Logger, +) { + if surface_list.contains(surface) { + slog::debug!( + logger, + "surface ({:?}) leaving output {:?}", + surface, + output.name() + ); + output.leave(surface); + surface_list.retain(|s| s != surface); + } +}