Skip to content

Commit

Permalink
Merge pull request #762 from Smithay/dev/sp-re-fix-surface-tracking
Browse files Browse the repository at this point in the history
desktop: Fix handling for output_enter/leave events
  • Loading branch information
Drakulix authored Sep 23, 2022
2 parents 2a11f18 + fb2f189 commit 25e70a2
Show file tree
Hide file tree
Showing 10 changed files with 285 additions and 203 deletions.
4 changes: 2 additions & 2 deletions anvil/src/udev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,7 @@ fn render_surface<'a>(
));
input_method.with_surface(|surface| {
elements.extend(AsRenderElements::<UdevRenderer<'a>>::render_elements(
&SurfaceTree::from_surface(surface, position),
&SurfaceTree::from_surface(surface),
position.to_physical_precise_round(scale),
scale,
));
Expand Down Expand Up @@ -908,7 +908,7 @@ fn render_surface<'a>(
if let Some(wl_surface) = dnd_icon.as_ref() {
if wl_surface.alive() {
elements.extend(AsRenderElements::<UdevRenderer<'a>>::render_elements(
&SurfaceTree::from_surface(wl_surface, cursor_pos.to_i32_round()),
&SurfaceTree::from_surface(wl_surface),
cursor_pos_scaled,
scale,
));
Expand Down
7 changes: 2 additions & 5 deletions anvil/src/winit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ pub fn run_winit(log: Logger) {
));
input_method.with_surface(|surface| {
elements.extend(AsRenderElements::<Gles2Renderer>::render_elements(
&smithay::desktop::space::SurfaceTree::from_surface(surface, position),
&smithay::desktop::space::SurfaceTree::from_surface(surface),
position.to_physical_precise_round(scale),
scale,
));
Expand All @@ -276,10 +276,7 @@ pub fn run_winit(log: Logger) {
if let Some(surface) = dnd_icon {
if surface.alive() {
elements.extend(AsRenderElements::<Gles2Renderer>::render_elements(
&smithay::desktop::space::SurfaceTree::from_surface(
surface,
cursor_pos.to_i32_round(),
),
&smithay::desktop::space::SurfaceTree::from_surface(surface),
cursor_pos_scaled,
scale,
));
Expand Down
7 changes: 2 additions & 5 deletions anvil/src/x11.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ pub fn run_x11(log: Logger) {
));
input_method.with_surface(|surface| {
elements.extend(AsRenderElements::<Gles2Renderer>::render_elements(
&smithay::desktop::space::SurfaceTree::from_surface(surface, position),
&smithay::desktop::space::SurfaceTree::from_surface(surface),
position.to_physical_precise_round(scale),
scale,
));
Expand All @@ -306,10 +306,7 @@ pub fn run_x11(log: Logger) {
if let Some(surface) = state.dnd_icon.as_ref() {
if surface.alive() {
elements.extend(AsRenderElements::<Gles2Renderer>::render_elements(
&smithay::desktop::space::SurfaceTree::from_surface(
surface,
cursor_pos.to_i32_round(),
),
&smithay::desktop::space::SurfaceTree::from_surface(surface),
cursor_pos_scaled,
scale,
));
Expand Down
30 changes: 23 additions & 7 deletions src/desktop/space/element/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,11 @@ pub trait SpaceElement: IsAlive {

/// Set the rendered state to activated, if applicable to this element
fn set_activate(&self, activated: bool);
/// The element is displayed on a given output
fn output_enter(&self, output: &Output);
/// The element is displayed on a given output.
///
/// Maybe called for an already entered output,
/// if the overlap changes
fn output_enter(&self, output: &Output, overlap: Rectangle<i32, Logical>);
/// The element left a given output
fn output_leave(&self, output: &Output);
/// Periodically called to update internal state, if necessary
Expand All @@ -83,12 +86,15 @@ impl<T: SpaceElement> SpaceElement for &T {
fn set_activate(&self, activated: bool) {
SpaceElement::set_activate(*self, activated)
}
fn output_enter(&self, output: &Output) {
SpaceElement::output_enter(*self, output)
fn output_enter(&self, output: &Output, overlap: Rectangle<i32, Logical>) {
SpaceElement::output_enter(*self, output, overlap)
}
fn output_leave(&self, output: &Output) {
SpaceElement::output_leave(*self, output)
}
fn refresh(&self) {
SpaceElement::refresh(*self)
}
}

#[derive(Debug)]
Expand All @@ -108,7 +114,17 @@ where
pub(super) fn z_index(&self) -> u8 {
match self {
#[cfg(feature = "wayland_frontend")]
SpaceElements::Layer { surface, .. } => surface.z_index(),
SpaceElements::Layer { surface, .. } => {
use crate::wayland::shell::wlr_layer::Layer;

let layer = match surface.layer() {
Layer::Background => RenderZindex::Background,
Layer::Bottom => RenderZindex::Bottom,
Layer::Top => RenderZindex::Top,
Layer::Overlay => RenderZindex::Overlay,
};
layer as u8
}
SpaceElements::Element(inner) => inner.element.z_index(),
}
}
Expand Down Expand Up @@ -311,14 +327,14 @@ macro_rules! space_elements_internal {
Self::_GenericCatcher(_) => unreachable!(),
}
}
fn output_enter(&self, output: &$crate::output::Output) {
fn output_enter(&self, output: &$crate::output::Output, overlap: $crate::utils::Rectangle<i32, $crate::utils::Logical>) {
match self {
$(
#[allow(unused_doc_comments)]
$(
#[$meta]
)*
Self::$body(x) => $crate::space_elements_internal!(@call output_enter; x, output)
Self::$body(x) => $crate::space_elements_internal!(@call output_enter; x, output, overlap)
),*,
Self::_GenericCatcher(_) => unreachable!(),
}
Expand Down
51 changes: 3 additions & 48 deletions src/desktop/space/element/wayland.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,20 @@
use crate::{
backend::renderer::Renderer,
desktop::space::*,
output::Output,
utils::{Logical, Physical, Point, Rectangle, Scale},
};
use crate::{
desktop::utils as desktop_utils,
wayland::compositor::{with_surface_tree_downward, TraversalAction},
utils::{Physical, Point, Scale},
};
use wayland_server::protocol::wl_surface::WlSurface;

/// A custom surface tree
#[derive(Debug)]
pub struct SurfaceTree {
location: Point<i32, Logical>,
surface: WlSurface,
}

impl SurfaceTree {
/// Create a surface tree from a surface
pub fn from_surface(surface: &WlSurface, location: impl Into<Point<i32, Logical>>) -> Self {
pub fn from_surface(surface: &WlSurface) -> Self {
SurfaceTree {
location: location.into(),
surface: surface.clone(),
}
}
Expand All @@ -32,45 +26,6 @@ impl IsAlive for SurfaceTree {
}
}

impl SpaceElement for SurfaceTree {
fn geometry(&self) -> Rectangle<i32, Logical> {
self.bbox()
}

fn bbox(&self) -> Rectangle<i32, Logical> {
desktop_utils::bbox_from_surface_tree(&self.surface, self.location)
}

fn is_in_input_region(&self, point: &Point<f64, Logical>) -> bool {
desktop_utils::under_from_surface_tree(&self.surface, *point, (0, 0), WindowSurfaceType::ALL)
.is_some()
}

fn set_activate(&self, _activated: bool) {}
fn output_enter(&self, output: &Output) {
with_surface_tree_downward(
&self.surface,
(),
|_, _, _| TraversalAction::DoChildren(()),
|wl_surface, _, _| {
output.enter(wl_surface);
},
|_, _, _| true,
);
}
fn output_leave(&self, output: &Output) {
with_surface_tree_downward(
&self.surface,
(),
|_, _, _| TraversalAction::DoChildren(()),
|wl_surface, _, _| {
output.leave(wl_surface);
},
|_, _, _| true,
);
}
}

impl<R> AsRenderElements<R> for SurfaceTree
where
R: Renderer + ImportAll,
Expand Down
34 changes: 23 additions & 11 deletions src/desktop/space/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::{
backend::renderer::{element::surface::WaylandSurfaceRenderElement, ImportAll},
desktop::{layer_map_for_output, LayerSurface, WindowSurfaceType},
};
use std::{collections::HashSet, fmt};
use std::{collections::HashMap, fmt};
#[cfg(feature = "wayland_frontend")]
use wayland_server::protocol::wl_surface::WlSurface;

Expand All @@ -39,7 +39,7 @@ crate::utils::ids::id_gen!(next_space_id, SPACE_ID, SPACE_IDS);
struct InnerElement<E> {
element: E,
location: Point<i32, Logical>,
outputs: HashSet<Output>,
outputs: HashMap<Output, Rectangle<i32, Logical>>,
}

/// Represents two dimensional plane to map windows and outputs upon.
Expand Down Expand Up @@ -101,7 +101,7 @@ impl<E: SpaceElement + PartialEq> Space<E> {
let outputs = if let Some(pos) = self.elements.iter().position(|inner| inner.element == element) {
self.elements.swap_remove(pos).outputs
} else {
HashSet::new()
HashMap::new()
};

let inner = InnerElement {
Expand Down Expand Up @@ -145,7 +145,10 @@ impl<E: SpaceElement + PartialEq> Space<E> {
// TODO: Requirements for E? Also provide retain?
pub fn unmap_elem(&mut self, element: &E) {
if let Some(pos) = self.elements.iter().position(|inner| &inner.element == element) {
self.elements.swap_remove(pos);
let elem = self.elements.swap_remove(pos);
for output in elem.outputs.keys() {
elem.element.output_leave(output);
}
}
}

Expand Down Expand Up @@ -299,6 +302,7 @@ impl<E: SpaceElement + PartialEq> Space<E> {
.find(|e| &e.element == elem)
.into_iter()
.flat_map(|e| &e.outputs)
.map(|(o, _)| o)
.cloned()
.collect()
}
Expand Down Expand Up @@ -327,16 +331,24 @@ impl<E: SpaceElement + PartialEq> Space<E> {
let bbox = e.bbox();

for (output, output_geometry) in &outputs {
// Check if the bounding box of the toplevel intersects with
// the output
if !output_geometry.overlaps(bbox) {
if e.outputs.remove(output) {
e.element.output_leave(output);
// Check if the bounding box of the toplevel intersects with the output
if let Some(overlap) = output_geometry.intersection(bbox) {
let old = e.outputs.insert(output.clone(), overlap);
if old.is_none() || matches!(old, Some(old_overlap) if old_overlap != overlap) {
e.element.output_enter(output, overlap);
}
} else if e.outputs.insert(output.clone()) {
e.element.output_enter(output);
} else if e.outputs.remove(output).is_some() {
e.element.output_leave(output);
}
}
e.outputs.retain(|output, _| {
if !outputs.iter().any(|(o, _)| o == output) {
e.element.output_leave(output);
false
} else {
true
}
});
}

self.elements.iter().for_each(|e| e.element.refresh());
Expand Down
40 changes: 2 additions & 38 deletions src/desktop/space/wayland/layer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,46 +6,10 @@ use crate::{
},
ImportAll, Renderer,
},
desktop::{
space::{RenderZindex, SpaceElement},
LayerSurface, PopupManager, WindowSurfaceType,
},
output::Output,
utils::{Logical, Physical, Point, Rectangle, Scale},
wayland::shell::wlr_layer::Layer,
desktop::{LayerSurface, PopupManager},
utils::{Physical, Point, Scale},
};

impl SpaceElement for LayerSurface {
fn geometry(&self) -> Rectangle<i32, Logical> {
self.bbox_with_popups()
}
fn bbox(&self) -> Rectangle<i32, Logical> {
self.bbox_with_popups()
}
fn is_in_input_region(&self, point: &Point<f64, Logical>) -> bool {
self.surface_under(*point, WindowSurfaceType::ALL).is_some()
}
/// Gets the z-index of this element on the specified space
fn z_index(&self) -> u8 {
let layer = self.layer();
let z_index = match layer {
Layer::Background => RenderZindex::Background,
Layer::Bottom => RenderZindex::Bottom,
Layer::Top => RenderZindex::Top,
Layer::Overlay => RenderZindex::Overlay,
};
z_index as u8
}

fn set_activate(&self, _activated: bool) {}
fn output_enter(&self, output: &Output) {
output.enter(self.wl_surface())
}
fn output_leave(&self, output: &Output) {
output.leave(self.wl_surface())
}
}

impl<R> AsRenderElements<R> for LayerSurface
where
R: Renderer + ImportAll,
Expand Down
Loading

0 comments on commit 25e70a2

Please sign in to comment.