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 element;
|
||||||
mod layer;
|
mod layer;
|
||||||
mod output;
|
mod output;
|
||||||
|
mod popup;
|
||||||
mod window;
|
mod window;
|
||||||
|
|
||||||
pub use self::element::*;
|
pub use self::element::*;
|
||||||
|
@ -486,6 +487,16 @@ impl Space {
|
||||||
let output_geo = Rectangle::from_loc_and_size(state.location, output_size);
|
let output_geo = Rectangle::from_loc_and_size(state.location, output_size);
|
||||||
let layer_map = layer_map_for_output(output);
|
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
|
// This will hold all the damage we need for this rendering step
|
||||||
let mut damage = Vec::<Rectangle<i32, Logical>>::new();
|
let mut damage = Vec::<Rectangle<i32, Logical>>::new();
|
||||||
// First add damage for windows gone
|
// First add damage for windows gone
|
||||||
|
@ -497,7 +508,9 @@ impl Space {
|
||||||
.windows
|
.windows
|
||||||
.iter()
|
.iter()
|
||||||
.map(|w| w as &SpaceElem<R>)
|
.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_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>))
|
.chain(custom_elements.iter().map(|c| c as &SpaceElem<R>))
|
||||||
.any(|e| ToplevelId::from(e) == *id)
|
.any(|e| ToplevelId::from(e) == *id)
|
||||||
{
|
{
|
||||||
|
@ -517,7 +530,9 @@ impl Space {
|
||||||
.windows
|
.windows
|
||||||
.iter()
|
.iter()
|
||||||
.map(|w| w as &SpaceElem<R>)
|
.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_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>))
|
.chain(custom_elements.iter().map(|c| c as &SpaceElem<R>))
|
||||||
{
|
{
|
||||||
let geo = element.geometry(self.id);
|
let geo = element.geometry(self.id);
|
||||||
|
@ -647,7 +662,9 @@ impl Space {
|
||||||
.windows
|
.windows
|
||||||
.iter()
|
.iter()
|
||||||
.map(|w| w as &SpaceElem<R>)
|
.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_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>))
|
.chain(custom_elements.iter().map(|c| c as &SpaceElem<R>))
|
||||||
.map(|elem| {
|
.map(|elem| {
|
||||||
let geo = elem.geometry(self.id);
|
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()
|
.into_iter()
|
||||||
.flat_map(|rect| rect.intersection(self.bbox())),
|
.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
|
damage
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue