desktop: Various cleanups
This commit is contained in:
parent
31b308836f
commit
cea88fdde0
|
@ -1,7 +1,9 @@
|
||||||
// TODO: Remove - but for now, this makes sure these files are not completely highlighted with warnings
|
// TODO: Remove - but for now, this makes sure these files are not completely highlighted with warnings
|
||||||
#![allow(missing_docs, clippy::all)]
|
#![allow(missing_docs, clippy::all)]
|
||||||
|
mod output;
|
||||||
mod popup;
|
mod popup;
|
||||||
mod space;
|
mod space;
|
||||||
|
pub mod utils;
|
||||||
mod window;
|
mod window;
|
||||||
|
|
||||||
pub use self::popup::*;
|
pub use self::popup::*;
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
use crate::{
|
||||||
|
utils::{Logical, Point, Rectangle},
|
||||||
|
wayland::output::Output,
|
||||||
|
};
|
||||||
|
use indexmap::IndexMap;
|
||||||
|
use wayland_server::protocol::wl_surface::WlSurface;
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
cell::{RefCell, RefMut},
|
||||||
|
collections::{HashMap, VecDeque},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
|
||||||
|
pub(super) enum ToplevelId {
|
||||||
|
Xdg(usize),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToplevelId {
|
||||||
|
pub fn is_xdg(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
ToplevelId::Xdg(_) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Default)]
|
||||||
|
pub(super) struct OutputState {
|
||||||
|
pub location: Point<i32, Logical>,
|
||||||
|
pub render_scale: f64,
|
||||||
|
|
||||||
|
// damage and last_state are in space coordinate space
|
||||||
|
pub old_damage: VecDeque<Vec<Rectangle<i32, Logical>>>,
|
||||||
|
pub last_state: IndexMap<ToplevelId, Rectangle<i32, Logical>>,
|
||||||
|
|
||||||
|
// surfaces for tracking enter and leave events
|
||||||
|
pub surfaces: Vec<WlSurface>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) type OutputUserdata = RefCell<HashMap<usize, OutputState>>;
|
||||||
|
pub(super) fn output_state(space: usize, o: &Output) -> RefMut<'_, OutputState> {
|
||||||
|
let userdata = o.user_data();
|
||||||
|
userdata.insert_if_missing(OutputUserdata::default);
|
||||||
|
RefMut::map(userdata.get::<OutputUserdata>().unwrap().borrow_mut(), |m| {
|
||||||
|
m.entry(space).or_default()
|
||||||
|
})
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
use super::{draw_window, Window};
|
use super::{draw_window, Window};
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::renderer::{utils::SurfaceState, Frame, ImportAll, Renderer, Transform},
|
backend::renderer::{utils::SurfaceState, Frame, ImportAll, Renderer, Transform},
|
||||||
|
desktop::output::*,
|
||||||
utils::{Logical, Point, Rectangle},
|
utils::{Logical, Point, Rectangle},
|
||||||
wayland::{
|
wayland::{
|
||||||
compositor::{with_surface_tree_downward, SubsurfaceCachedState, TraversalAction},
|
compositor::{with_surface_tree_downward, SubsurfaceCachedState, TraversalAction},
|
||||||
|
@ -55,28 +56,6 @@ fn window_state(space: usize, w: &Window) -> RefMut<'_, WindowState> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
|
||||||
struct OutputState {
|
|
||||||
location: Point<i32, Logical>,
|
|
||||||
render_scale: f64,
|
|
||||||
|
|
||||||
// damage and last_state are in space coordinate space
|
|
||||||
old_damage: VecDeque<Vec<Rectangle<i32, Logical>>>,
|
|
||||||
last_state: IndexMap<usize, Rectangle<i32, Logical>>,
|
|
||||||
|
|
||||||
// surfaces for tracking enter and leave events
|
|
||||||
surfaces: Vec<WlSurface>,
|
|
||||||
}
|
|
||||||
|
|
||||||
type OutputUserdata = RefCell<HashMap<usize, OutputState>>;
|
|
||||||
fn output_state(space: usize, o: &Output) -> RefMut<'_, OutputState> {
|
|
||||||
let userdata = o.user_data();
|
|
||||||
userdata.insert_if_missing(OutputUserdata::default);
|
|
||||||
RefMut::map(userdata.get::<OutputUserdata>().unwrap().borrow_mut(), |m| {
|
|
||||||
m.entry(space).or_default()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Maybe replace UnmanagedResource if nothing else comes up?
|
// TODO: Maybe replace UnmanagedResource if nothing else comes up?
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum SpaceError {
|
pub enum SpaceError {
|
||||||
|
@ -118,12 +97,17 @@ impl Space {
|
||||||
///
|
///
|
||||||
/// This can safely be called on an already mapped window
|
/// This can safely be called on an already mapped window
|
||||||
pub fn map_window(&mut self, window: &Window, location: Point<i32, Logical>) {
|
pub fn map_window(&mut self, window: &Window, location: Point<i32, Logical>) {
|
||||||
self.raise_window(window);
|
self.insert_window(window);
|
||||||
window_state(self.id, window).location = location;
|
window_state(self.id, window).location = location;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn raise_window(&mut self, window: &Window) {
|
pub fn raise_window(&mut self, window: &Window) {
|
||||||
self.windows.shift_remove(window);
|
if self.windows.shift_remove(window) {
|
||||||
|
self.insert_window(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn insert_window(&mut self, window: &Window) {
|
||||||
self.windows.insert(window.clone());
|
self.windows.insert(window.clone());
|
||||||
|
|
||||||
// TODO: should this be handled by us?
|
// TODO: should this be handled by us?
|
||||||
|
@ -144,7 +128,7 @@ impl Space {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate window in z-order back to front
|
/// Iterate window in z-order back to front
|
||||||
pub fn windows(&self) -> impl Iterator<Item = &Window> {
|
pub fn windows(&self) -> impl DoubleEndedIterator<Item = &Window> {
|
||||||
self.windows.iter()
|
self.windows.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,6 +140,14 @@ impl Space {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a reference to the output under a given point, if any
|
||||||
|
pub fn output_under(&self, point: Point<f64, Logical>) -> Option<&Output> {
|
||||||
|
self.outputs.iter().rev().find(|o| {
|
||||||
|
let bbox = self.output_geometry(o);
|
||||||
|
bbox.map(|bbox| bbox.to_f64().contains(point)).unwrap_or(false)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn window_for_surface(&self, surface: &WlSurface) -> Option<&Window> {
|
pub fn window_for_surface(&self, surface: &WlSurface) -> Option<&Window> {
|
||||||
if !surface.as_ref().is_alive() {
|
if !surface.as_ref().is_alive() {
|
||||||
return None;
|
return None;
|
||||||
|
@ -405,7 +397,7 @@ impl Space {
|
||||||
.last_state
|
.last_state
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(id, w)| {
|
.filter_map(|(id, w)| {
|
||||||
if !self.windows.iter().any(|w| w.0.id == *id) {
|
if !self.windows.iter().any(|w| ToplevelId::Xdg(w.0.id) == *id) {
|
||||||
Some(*w)
|
Some(*w)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -413,14 +405,14 @@ impl Space {
|
||||||
})
|
})
|
||||||
.collect::<Vec<Rectangle<i32, Logical>>>()
|
.collect::<Vec<Rectangle<i32, Logical>>>()
|
||||||
{
|
{
|
||||||
slog::trace!(self.logger, "Removing window at: {:?}", old_window);
|
slog::trace!(self.logger, "Removing toplevel at: {:?}", old_window);
|
||||||
damage.push(old_window);
|
damage.push(old_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
// lets iterate front to back and figure out, what new windows or unmoved windows we have
|
// lets iterate front to back and figure out, what new windows or unmoved windows we have
|
||||||
for window in self.windows.iter().rev() {
|
for window in self.windows.iter() {
|
||||||
let geo = window_rect_with_popups(window, &self.id);
|
let geo = window_rect_with_popups(window, &self.id);
|
||||||
let old_geo = state.last_state.get(&window.0.id).cloned();
|
let old_geo = state.last_state.get(&ToplevelId::Xdg(window.0.id)).cloned();
|
||||||
|
|
||||||
// window was moved or resized
|
// window was moved or resized
|
||||||
if old_geo.map(|old_geo| old_geo != geo).unwrap_or(false) {
|
if old_geo.map(|old_geo| old_geo != geo).unwrap_or(false) {
|
||||||
|
@ -540,7 +532,7 @@ impl Space {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|window| {
|
.map(|window| {
|
||||||
let wgeo = window_rect_with_popups(window, &self.id);
|
let wgeo = window_rect_with_popups(window, &self.id);
|
||||||
(window.0.id, wgeo)
|
(ToplevelId::Xdg(window.0.id), wgeo)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
state.old_damage.push_front(new_damage);
|
state.old_damage.push_front(new_damage);
|
||||||
|
|
|
@ -0,0 +1,199 @@
|
||||||
|
use crate::{
|
||||||
|
backend::renderer::utils::SurfaceState,
|
||||||
|
utils::{Logical, Point, Rectangle, Size},
|
||||||
|
wayland::compositor::{
|
||||||
|
with_surface_tree_downward, with_surface_tree_upward, Damage, SubsurfaceCachedState,
|
||||||
|
SurfaceAttributes, TraversalAction,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use wayland_server::protocol::wl_surface;
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
|
impl SurfaceState {
|
||||||
|
/// Returns the size of the surface.
|
||||||
|
pub fn size(&self) -> Option<Size<i32, Logical>> {
|
||||||
|
self.buffer_dimensions
|
||||||
|
.map(|dims| dims.to_logical(self.buffer_scale))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn contains_point(&self, attrs: &SurfaceAttributes, point: Point<f64, Logical>) -> bool {
|
||||||
|
let size = match self.size() {
|
||||||
|
None => return false, // If the surface has no size, it can't have an input region.
|
||||||
|
Some(size) => size,
|
||||||
|
};
|
||||||
|
|
||||||
|
let rect = Rectangle {
|
||||||
|
loc: (0, 0).into(),
|
||||||
|
size,
|
||||||
|
}
|
||||||
|
.to_f64();
|
||||||
|
|
||||||
|
// The input region is always within the surface itself, so if the surface itself doesn't contain the
|
||||||
|
// point we can return false.
|
||||||
|
if !rect.contains(point) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there's no input region, we're done.
|
||||||
|
if attrs.input_region.is_none() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
attrs
|
||||||
|
.input_region
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.contains(point.to_i32_floor())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bbox_from_surface_tree<P>(surface: &wl_surface::WlSurface, location: P) -> Rectangle<i32, Logical>
|
||||||
|
where
|
||||||
|
P: Into<Point<i32, Logical>>,
|
||||||
|
{
|
||||||
|
let location = location.into();
|
||||||
|
let mut bounding_box = Rectangle::from_loc_and_size(location, (0, 0));
|
||||||
|
with_surface_tree_downward(
|
||||||
|
surface,
|
||||||
|
location,
|
||||||
|
|_, states, loc: &Point<i32, Logical>| {
|
||||||
|
let mut loc = *loc;
|
||||||
|
let data = states.data_map.get::<RefCell<SurfaceState>>();
|
||||||
|
|
||||||
|
if let Some(size) = data.and_then(|d| d.borrow().size()) {
|
||||||
|
if states.role == Some("subsurface") {
|
||||||
|
let current = states.cached_state.current::<SubsurfaceCachedState>();
|
||||||
|
loc += current.location;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the bounding box.
|
||||||
|
bounding_box = bounding_box.merge(Rectangle::from_loc_and_size(loc, size));
|
||||||
|
|
||||||
|
TraversalAction::DoChildren(loc)
|
||||||
|
} else {
|
||||||
|
// If the parent surface is unmapped, then the child surfaces are hidden as
|
||||||
|
// well, no need to consider them here.
|
||||||
|
TraversalAction::SkipChildren
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|_, _, _| {},
|
||||||
|
|_, _, _| true,
|
||||||
|
);
|
||||||
|
bounding_box
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn damage_from_surface_tree<P>(
|
||||||
|
surface: &wl_surface::WlSurface,
|
||||||
|
location: P,
|
||||||
|
) -> Vec<Rectangle<i32, Logical>>
|
||||||
|
where
|
||||||
|
P: Into<Point<i32, Logical>>,
|
||||||
|
{
|
||||||
|
let mut damage = Vec::new();
|
||||||
|
with_surface_tree_upward(
|
||||||
|
surface,
|
||||||
|
location.into(),
|
||||||
|
|_surface, states, location| {
|
||||||
|
let mut location = *location;
|
||||||
|
if let Some(data) = states.data_map.get::<RefCell<SurfaceState>>() {
|
||||||
|
let data = data.borrow();
|
||||||
|
if data.texture.is_none() {
|
||||||
|
if states.role == Some("subsurface") {
|
||||||
|
let current = states.cached_state.current::<SubsurfaceCachedState>();
|
||||||
|
location += current.location;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TraversalAction::DoChildren(location)
|
||||||
|
},
|
||||||
|
|_surface, states, location| {
|
||||||
|
let mut location = *location;
|
||||||
|
if let Some(data) = states.data_map.get::<RefCell<SurfaceState>>() {
|
||||||
|
let data = data.borrow();
|
||||||
|
let attributes = states.cached_state.current::<SurfaceAttributes>();
|
||||||
|
|
||||||
|
if data.texture.is_none() {
|
||||||
|
if states.role == Some("subsurface") {
|
||||||
|
let current = states.cached_state.current::<SubsurfaceCachedState>();
|
||||||
|
location += current.location;
|
||||||
|
}
|
||||||
|
|
||||||
|
damage.extend(attributes.damage.iter().map(|dmg| {
|
||||||
|
let mut rect = match dmg {
|
||||||
|
Damage::Buffer(rect) => rect.to_logical(attributes.buffer_scale),
|
||||||
|
Damage::Surface(rect) => *rect,
|
||||||
|
};
|
||||||
|
rect.loc += location;
|
||||||
|
rect
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|_, _, _| true,
|
||||||
|
);
|
||||||
|
damage
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn under_from_surface_tree<P>(
|
||||||
|
surface: &wl_surface::WlSurface,
|
||||||
|
point: Point<f64, Logical>,
|
||||||
|
location: P,
|
||||||
|
) -> Option<(wl_surface::WlSurface, Point<i32, Logical>)>
|
||||||
|
where
|
||||||
|
P: Into<Point<i32, Logical>>,
|
||||||
|
{
|
||||||
|
let found = RefCell::new(None);
|
||||||
|
with_surface_tree_downward(
|
||||||
|
surface,
|
||||||
|
location.into(),
|
||||||
|
|wl_surface, states, location: &Point<i32, Logical>| {
|
||||||
|
let mut location = *location;
|
||||||
|
let data = states.data_map.get::<RefCell<SurfaceState>>();
|
||||||
|
|
||||||
|
if states.role == Some("subsurface") {
|
||||||
|
let current = states.cached_state.current::<SubsurfaceCachedState>();
|
||||||
|
location += current.location;
|
||||||
|
}
|
||||||
|
|
||||||
|
let contains_the_point = data
|
||||||
|
.map(|data| {
|
||||||
|
data.borrow()
|
||||||
|
.contains_point(&*states.cached_state.current(), point - location.to_f64())
|
||||||
|
})
|
||||||
|
.unwrap_or(false);
|
||||||
|
if contains_the_point {
|
||||||
|
*found.borrow_mut() = Some((wl_surface.clone(), location));
|
||||||
|
}
|
||||||
|
|
||||||
|
TraversalAction::DoChildren(location)
|
||||||
|
},
|
||||||
|
|_, _, _| {},
|
||||||
|
|_, _, _| {
|
||||||
|
// only continue if the point is not found
|
||||||
|
found.borrow().is_none()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
found.into_inner()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send_frames_surface_tree(surface: &wl_surface::WlSurface, time: u32) {
|
||||||
|
with_surface_tree_downward(
|
||||||
|
surface,
|
||||||
|
(),
|
||||||
|
|_, _, &()| TraversalAction::DoChildren(()),
|
||||||
|
|_surf, states, &()| {
|
||||||
|
// the surface may not have any user_data if it is a subsurface and has not
|
||||||
|
// yet been commited
|
||||||
|
for callback in states
|
||||||
|
.cached_state
|
||||||
|
.current::<SurfaceAttributes>()
|
||||||
|
.frame_callbacks
|
||||||
|
.drain(..)
|
||||||
|
{
|
||||||
|
callback.done(time);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|_, _, &()| true,
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,20 +1,13 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::renderer::{
|
backend::renderer::{utils::draw_surface_tree, Frame, ImportAll, Renderer, Texture},
|
||||||
utils::{draw_surface_tree, SurfaceState},
|
desktop::{utils::*, PopupManager},
|
||||||
Frame, ImportAll, Renderer, Texture,
|
utils::{Logical, Point, Rectangle},
|
||||||
},
|
|
||||||
desktop::PopupManager,
|
|
||||||
utils::{Logical, Point, Rectangle, Size},
|
|
||||||
wayland::{
|
wayland::{
|
||||||
compositor::{
|
compositor::with_states,
|
||||||
with_states, with_surface_tree_downward, with_surface_tree_upward, Damage, SubsurfaceCachedState,
|
|
||||||
SurfaceAttributes, TraversalAction,
|
|
||||||
},
|
|
||||||
shell::xdg::{SurfaceCachedState, ToplevelSurface},
|
shell::xdg::{SurfaceCachedState, ToplevelSurface},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
|
||||||
collections::HashSet,
|
collections::HashSet,
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
|
@ -25,7 +18,7 @@ use std::{
|
||||||
};
|
};
|
||||||
use wayland_commons::user_data::UserDataMap;
|
use wayland_commons::user_data::UserDataMap;
|
||||||
use wayland_protocols::xdg_shell::server::xdg_toplevel;
|
use wayland_protocols::xdg_shell::server::xdg_toplevel;
|
||||||
use wayland_server::protocol::{wl_buffer, wl_surface};
|
use wayland_server::protocol::wl_surface;
|
||||||
|
|
||||||
static WINDOW_ID: AtomicUsize = AtomicUsize::new(0);
|
static WINDOW_ID: AtomicUsize = AtomicUsize::new(0);
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
|
@ -101,44 +94,6 @@ impl Kind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SurfaceState {
|
|
||||||
/// Returns the size of the surface.
|
|
||||||
pub fn size(&self) -> Option<Size<i32, Logical>> {
|
|
||||||
self.buffer_dimensions
|
|
||||||
.map(|dims| dims.to_logical(self.buffer_scale))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn contains_point(&self, attrs: &SurfaceAttributes, point: Point<f64, Logical>) -> bool {
|
|
||||||
let size = match self.size() {
|
|
||||||
None => return false, // If the surface has no size, it can't have an input region.
|
|
||||||
Some(size) => size,
|
|
||||||
};
|
|
||||||
|
|
||||||
let rect = Rectangle {
|
|
||||||
loc: (0, 0).into(),
|
|
||||||
size,
|
|
||||||
}
|
|
||||||
.to_f64();
|
|
||||||
|
|
||||||
// The input region is always within the surface itself, so if the surface itself doesn't contain the
|
|
||||||
// point we can return false.
|
|
||||||
if !rect.contains(point) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there's no input region, we're done.
|
|
||||||
if attrs.input_region.is_none() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
attrs
|
|
||||||
.input_region
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.contains(point.to_i32_floor())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(super) struct WindowInner {
|
pub(super) struct WindowInner {
|
||||||
pub(super) id: usize,
|
pub(super) id: usize,
|
||||||
|
@ -317,154 +272,6 @@ impl Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn damage_from_surface_tree<P>(surface: &wl_surface::WlSurface, location: P) -> Vec<Rectangle<i32, Logical>>
|
|
||||||
where
|
|
||||||
P: Into<Point<i32, Logical>>,
|
|
||||||
{
|
|
||||||
let mut damage = Vec::new();
|
|
||||||
with_surface_tree_upward(
|
|
||||||
surface,
|
|
||||||
location.into(),
|
|
||||||
|_surface, states, location| {
|
|
||||||
let mut location = *location;
|
|
||||||
if let Some(data) = states.data_map.get::<RefCell<SurfaceState>>() {
|
|
||||||
let data = data.borrow();
|
|
||||||
if data.texture.is_none() {
|
|
||||||
if states.role == Some("subsurface") {
|
|
||||||
let current = states.cached_state.current::<SubsurfaceCachedState>();
|
|
||||||
location += current.location;
|
|
||||||
}
|
|
||||||
return TraversalAction::DoChildren(location);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TraversalAction::SkipChildren
|
|
||||||
},
|
|
||||||
|_surface, states, location| {
|
|
||||||
let mut location = *location;
|
|
||||||
if let Some(data) = states.data_map.get::<RefCell<SurfaceState>>() {
|
|
||||||
let data = data.borrow();
|
|
||||||
let attributes = states.cached_state.current::<SurfaceAttributes>();
|
|
||||||
|
|
||||||
if data.texture.is_none() {
|
|
||||||
if states.role == Some("subsurface") {
|
|
||||||
let current = states.cached_state.current::<SubsurfaceCachedState>();
|
|
||||||
location += current.location;
|
|
||||||
}
|
|
||||||
|
|
||||||
damage.extend(attributes.damage.iter().map(|dmg| {
|
|
||||||
let mut rect = match dmg {
|
|
||||||
Damage::Buffer(rect) => rect.to_logical(attributes.buffer_scale),
|
|
||||||
Damage::Surface(rect) => *rect,
|
|
||||||
};
|
|
||||||
rect.loc += location;
|
|
||||||
rect
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|_, _, _| true,
|
|
||||||
);
|
|
||||||
damage
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bbox_from_surface_tree<P>(surface: &wl_surface::WlSurface, location: P) -> Rectangle<i32, Logical>
|
|
||||||
where
|
|
||||||
P: Into<Point<i32, Logical>>,
|
|
||||||
{
|
|
||||||
let location = location.into();
|
|
||||||
let mut bounding_box = Rectangle::from_loc_and_size(location, (0, 0));
|
|
||||||
with_surface_tree_downward(
|
|
||||||
surface,
|
|
||||||
location,
|
|
||||||
|_, states, loc: &Point<i32, Logical>| {
|
|
||||||
let mut loc = *loc;
|
|
||||||
let data = states.data_map.get::<RefCell<SurfaceState>>();
|
|
||||||
|
|
||||||
if let Some(size) = data.and_then(|d| d.borrow().size()) {
|
|
||||||
if states.role == Some("subsurface") {
|
|
||||||
let current = states.cached_state.current::<SubsurfaceCachedState>();
|
|
||||||
loc += current.location;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the bounding box.
|
|
||||||
bounding_box = bounding_box.merge(Rectangle::from_loc_and_size(loc, size));
|
|
||||||
|
|
||||||
TraversalAction::DoChildren(loc)
|
|
||||||
} else {
|
|
||||||
// If the parent surface is unmapped, then the child surfaces are hidden as
|
|
||||||
// well, no need to consider them here.
|
|
||||||
TraversalAction::SkipChildren
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|_, _, _| {},
|
|
||||||
|_, _, _| true,
|
|
||||||
);
|
|
||||||
bounding_box
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn under_from_surface_tree<P>(
|
|
||||||
surface: &wl_surface::WlSurface,
|
|
||||||
point: Point<f64, Logical>,
|
|
||||||
location: P,
|
|
||||||
) -> Option<(wl_surface::WlSurface, Point<i32, Logical>)>
|
|
||||||
where
|
|
||||||
P: Into<Point<i32, Logical>>,
|
|
||||||
{
|
|
||||||
let found = RefCell::new(None);
|
|
||||||
with_surface_tree_downward(
|
|
||||||
surface,
|
|
||||||
location.into(),
|
|
||||||
|wl_surface, states, location: &Point<i32, Logical>| {
|
|
||||||
let mut location = *location;
|
|
||||||
let data = states.data_map.get::<RefCell<SurfaceState>>();
|
|
||||||
|
|
||||||
if states.role == Some("subsurface") {
|
|
||||||
let current = states.cached_state.current::<SubsurfaceCachedState>();
|
|
||||||
location += current.location;
|
|
||||||
}
|
|
||||||
|
|
||||||
let contains_the_point = data
|
|
||||||
.map(|data| {
|
|
||||||
data.borrow()
|
|
||||||
.contains_point(&*states.cached_state.current(), point - location.to_f64())
|
|
||||||
})
|
|
||||||
.unwrap_or(false);
|
|
||||||
if contains_the_point {
|
|
||||||
*found.borrow_mut() = Some((wl_surface.clone(), location));
|
|
||||||
}
|
|
||||||
|
|
||||||
TraversalAction::DoChildren(location)
|
|
||||||
},
|
|
||||||
|_, _, _| {},
|
|
||||||
|_, _, _| {
|
|
||||||
// only continue if the point is not found
|
|
||||||
found.borrow().is_none()
|
|
||||||
},
|
|
||||||
);
|
|
||||||
found.into_inner()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn send_frames_surface_tree(surface: &wl_surface::WlSurface, time: u32) {
|
|
||||||
with_surface_tree_downward(
|
|
||||||
surface,
|
|
||||||
(),
|
|
||||||
|_, _, &()| TraversalAction::DoChildren(()),
|
|
||||||
|_surf, states, &()| {
|
|
||||||
// the surface may not have any user_data if it is a subsurface and has not
|
|
||||||
// yet been commited
|
|
||||||
for callback in states
|
|
||||||
.cached_state
|
|
||||||
.current::<SurfaceAttributes>()
|
|
||||||
.frame_callbacks
|
|
||||||
.drain(..)
|
|
||||||
{
|
|
||||||
callback.done(time);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|_, _, &()| true,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn draw_window<R, E, F, T>(
|
pub fn draw_window<R, E, F, T>(
|
||||||
renderer: &mut R,
|
renderer: &mut R,
|
||||||
frame: &mut F,
|
frame: &mut F,
|
||||||
|
|
|
@ -100,7 +100,7 @@ pub struct PhysicalProperties {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Inner {
|
pub(crate) struct Inner {
|
||||||
name: String,
|
name: String,
|
||||||
log: ::slog::Logger,
|
log: ::slog::Logger,
|
||||||
instances: Vec<WlOutput>,
|
instances: Vec<WlOutput>,
|
||||||
|
@ -170,7 +170,7 @@ impl Inner {
|
||||||
/// about any change in the properties of this output.
|
/// about any change in the properties of this output.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Output {
|
pub struct Output {
|
||||||
inner: InnerType,
|
pub(crate) inner: InnerType,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Output {
|
impl Output {
|
||||||
|
@ -274,6 +274,11 @@ impl Output {
|
||||||
self.inner.0.lock().unwrap().transform
|
self.inner.0.lock().unwrap().transform
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the currenly advertised scale of the output
|
||||||
|
pub fn current_scale(&self) -> i32 {
|
||||||
|
self.inner.0.lock().unwrap().scale
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the name of the output
|
/// Returns the name of the output
|
||||||
pub fn name(&self) -> String {
|
pub fn name(&self) -> String {
|
||||||
self.inner.0.lock().unwrap().name.clone()
|
self.inner.0.lock().unwrap().name.clone()
|
||||||
|
|
Loading…
Reference in New Issue