Merge pull request #463 from Smithay/fix/popup_damage
This commit is contained in:
commit
c9a2eb7ed2
|
@ -24,6 +24,7 @@ use wayland_server::protocol::wl_surface::WlSurface;
|
|||
mod element;
|
||||
mod layer;
|
||||
mod output;
|
||||
mod popup;
|
||||
mod window;
|
||||
|
||||
pub use self::element::*;
|
||||
|
@ -486,6 +487,16 @@ impl Space {
|
|||
let output_geo = Rectangle::from_loc_and_size(state.location, output_size);
|
||||
let layer_map = layer_map_for_output(output);
|
||||
|
||||
let window_popups = self
|
||||
.windows
|
||||
.iter()
|
||||
.flat_map(|w| w.popup_elements::<R>(self.id))
|
||||
.collect::<Vec<_>>();
|
||||
let layer_popups = layer_map
|
||||
.layers()
|
||||
.flat_map(|l| l.popup_elements::<R>(self.id))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// This will hold all the damage we need for this rendering step
|
||||
let mut damage = Vec::<Rectangle<i32, Logical>>::new();
|
||||
// First add damage for windows gone
|
||||
|
@ -497,7 +508,9 @@ impl Space {
|
|||
.windows
|
||||
.iter()
|
||||
.map(|w| w as &SpaceElem<R>)
|
||||
.chain(window_popups.iter().map(|p| p as &SpaceElem<R>))
|
||||
.chain(layer_map.layers().map(|l| l as &SpaceElem<R>))
|
||||
.chain(layer_popups.iter().map(|p| p as &SpaceElem<R>))
|
||||
.chain(custom_elements.iter().map(|c| c as &SpaceElem<R>))
|
||||
.any(|e| ToplevelId::from(e) == *id)
|
||||
{
|
||||
|
@ -517,7 +530,9 @@ impl Space {
|
|||
.windows
|
||||
.iter()
|
||||
.map(|w| w as &SpaceElem<R>)
|
||||
.chain(window_popups.iter().map(|p| p as &SpaceElem<R>))
|
||||
.chain(layer_map.layers().map(|l| l as &SpaceElem<R>))
|
||||
.chain(layer_popups.iter().map(|p| p as &SpaceElem<R>))
|
||||
.chain(custom_elements.iter().map(|c| c as &SpaceElem<R>))
|
||||
{
|
||||
let geo = element.geometry(self.id);
|
||||
|
@ -647,7 +662,9 @@ impl Space {
|
|||
.windows
|
||||
.iter()
|
||||
.map(|w| w as &SpaceElem<R>)
|
||||
.chain(window_popups.iter().map(|p| p as &SpaceElem<R>))
|
||||
.chain(layer_map.layers().map(|l| l as &SpaceElem<R>))
|
||||
.chain(layer_popups.iter().map(|p| p as &SpaceElem<R>))
|
||||
.chain(custom_elements.iter().map(|c| c as &SpaceElem<R>))
|
||||
.map(|elem| {
|
||||
let geo = elem.geometry(self.id);
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
use crate::{
|
||||
backend::renderer::{Frame, ImportAll, Renderer, Texture},
|
||||
desktop::{
|
||||
layer::LayerSurface,
|
||||
popup::{PopupKind, PopupManager},
|
||||
space::{window_loc, Space, SpaceElement},
|
||||
utils::{bbox_from_surface_tree, damage_from_surface_tree},
|
||||
window::Window,
|
||||
},
|
||||
utils::{Logical, Point, Rectangle},
|
||||
wayland::output::Output,
|
||||
};
|
||||
use std::any::TypeId;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RenderPopup {
|
||||
location: Point<i32, Logical>,
|
||||
popup: PopupKind,
|
||||
}
|
||||
|
||||
impl Window {
|
||||
pub(super) fn popup_elements<R>(&self, space_id: usize) -> impl Iterator<Item = RenderPopup>
|
||||
where
|
||||
R: Renderer + ImportAll + 'static,
|
||||
R::TextureId: 'static,
|
||||
R::Error: 'static,
|
||||
R::Frame: 'static,
|
||||
{
|
||||
let loc = window_loc(self, &space_id) + self.geometry().loc;
|
||||
self.toplevel()
|
||||
.get_surface()
|
||||
.map(move |surface| {
|
||||
PopupManager::popups_for_surface(surface)
|
||||
.ok()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.map(move |(popup, location)| {
|
||||
let offset = loc + location - popup.geometry().loc;
|
||||
RenderPopup {
|
||||
location: offset,
|
||||
popup,
|
||||
}
|
||||
})
|
||||
})
|
||||
.into_iter()
|
||||
.flatten()
|
||||
}
|
||||
}
|
||||
|
||||
impl LayerSurface {
|
||||
pub(super) fn popup_elements<R>(&self, space_id: usize) -> impl Iterator<Item = RenderPopup>
|
||||
where
|
||||
R: Renderer + ImportAll + 'static,
|
||||
R::TextureId: 'static,
|
||||
R::Error: 'static,
|
||||
R::Frame: 'static,
|
||||
{
|
||||
type SpaceElem<R> =
|
||||
dyn SpaceElement<R, <R as Renderer>::Frame, <R as Renderer>::Error, <R as Renderer>::TextureId>;
|
||||
|
||||
let loc = (self as &SpaceElem<R>).geometry(space_id).loc;
|
||||
self.get_surface()
|
||||
.map(move |surface| {
|
||||
PopupManager::popups_for_surface(surface)
|
||||
.ok()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.map(move |(popup, location)| {
|
||||
let offset = loc + location - popup.geometry().loc;
|
||||
RenderPopup {
|
||||
location: offset,
|
||||
popup,
|
||||
}
|
||||
})
|
||||
})
|
||||
.into_iter()
|
||||
.flatten()
|
||||
}
|
||||
}
|
||||
|
||||
impl<R, F, E, T> SpaceElement<R, F, E, T> for RenderPopup
|
||||
where
|
||||
R: Renderer<Error = E, TextureId = T, Frame = F> + ImportAll,
|
||||
F: Frame<Error = E, TextureId = T>,
|
||||
E: std::error::Error,
|
||||
T: Texture + 'static,
|
||||
{
|
||||
fn id(&self) -> usize {
|
||||
self.popup
|
||||
.get_surface()
|
||||
.map(|s| s.as_ref().id() as usize)
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
fn type_of(&self) -> TypeId {
|
||||
TypeId::of::<RenderPopup>()
|
||||
}
|
||||
|
||||
fn geometry(&self, _space_id: usize) -> Rectangle<i32, Logical> {
|
||||
if let Some(surface) = self.popup.get_surface() {
|
||||
bbox_from_surface_tree(surface, self.location)
|
||||
} else {
|
||||
Rectangle::from_loc_and_size((0, 0), (0, 0))
|
||||
}
|
||||
}
|
||||
|
||||
fn accumulated_damage(&self, for_values: Option<(&Space, &Output)>) -> Vec<Rectangle<i32, Logical>> {
|
||||
if let Some(surface) = self.popup.get_surface() {
|
||||
damage_from_surface_tree(surface, (0, 0), for_values)
|
||||
} else {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn draw(
|
||||
&self,
|
||||
_space_id: usize,
|
||||
_renderer: &mut R,
|
||||
_frame: &mut F,
|
||||
_scale: f64,
|
||||
_location: Point<i32, Logical>,
|
||||
_damage: &[Rectangle<i32, Logical>],
|
||||
_log: &slog::Logger,
|
||||
) -> Result<(), R::Error> {
|
||||
// popups are special, we track them, but they render with their parents
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -258,18 +258,6 @@ impl Window {
|
|||
.into_iter()
|
||||
.flat_map(|rect| rect.intersection(self.bbox())),
|
||||
);
|
||||
for (popup, location) in PopupManager::popups_for_surface(surface)
|
||||
.ok()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
{
|
||||
if let Some(surface) = popup.get_surface() {
|
||||
let offset = self.geometry().loc + location - popup.geometry().loc;
|
||||
let bbox = bbox_from_surface_tree(surface, offset);
|
||||
let popup_damage = damage_from_surface_tree(surface, offset, for_values);
|
||||
damage.extend(popup_damage.into_iter().flat_map(|rect| rect.intersection(bbox)));
|
||||
}
|
||||
}
|
||||
}
|
||||
damage
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue