Consistently use buffer coordinates
- Moves `Transform` into utils::geometry - Changes conversion from and into buffer-coordinates to take `Transform` arguments. - `Renderer` take `Buffer`-space damage now - buffer_transform is taken into account everywhere
This commit is contained in:
parent
f76311227b
commit
439d5a7820
|
@ -839,7 +839,7 @@ impl EGLBufferReader {
|
|||
pub fn egl_buffer_dimensions(
|
||||
&self,
|
||||
buffer: &WlBuffer,
|
||||
) -> Option<crate::utils::Size<i32, crate::utils::Physical>> {
|
||||
) -> Option<crate::utils::Size<i32, crate::utils::Buffer>> {
|
||||
if !buffer.as_ref().is_alive() {
|
||||
debug!(self.logger, "Suplied buffer is no longer alive");
|
||||
return None;
|
||||
|
|
|
@ -13,7 +13,7 @@ use cgmath::{prelude::*, Matrix3, Vector2, Vector3};
|
|||
mod shaders;
|
||||
mod version;
|
||||
|
||||
use super::{Bind, Frame, Renderer, Texture, TextureFilter, Transform, Unbind};
|
||||
use super::{Bind, Frame, Renderer, Texture, TextureFilter, Unbind};
|
||||
use crate::backend::allocator::{
|
||||
dmabuf::{Dmabuf, WeakDmabuf},
|
||||
Format,
|
||||
|
@ -23,7 +23,7 @@ use crate::backend::egl::{
|
|||
EGLContext, EGLSurface, MakeCurrentError,
|
||||
};
|
||||
use crate::backend::SwapBuffersError;
|
||||
use crate::utils::{Buffer, Physical, Rectangle, Size};
|
||||
use crate::utils::{Buffer, Physical, Rectangle, Size, Transform};
|
||||
|
||||
#[cfg(all(feature = "wayland_frontend", feature = "use_system_lib"))]
|
||||
use super::ImportEgl;
|
||||
|
@ -1250,7 +1250,7 @@ impl Frame for Gles2Frame {
|
|||
texture: &Self::TextureId,
|
||||
src: Rectangle<i32, Buffer>,
|
||||
dest: Rectangle<f64, Physical>,
|
||||
damage: &[Rectangle<i32, Physical>],
|
||||
damage: &[Rectangle<i32, Buffer>],
|
||||
transform: Transform,
|
||||
alpha: f32,
|
||||
) -> Result<(), Self::Error> {
|
||||
|
@ -1266,7 +1266,7 @@ impl Frame for Gles2Frame {
|
|||
assert_eq!(mat, mat * transform.invert().matrix());
|
||||
assert_eq!(transform.matrix(), Matrix3::<f32>::identity());
|
||||
}
|
||||
mat = mat * transform.invert().matrix();
|
||||
mat = mat * transform.matrix();
|
||||
mat = mat * Matrix3::from_translation(Vector2::new(-0.5, -0.5));
|
||||
|
||||
// this matrix should be regular, we can expect invert to succeed
|
||||
|
@ -1290,24 +1290,24 @@ impl Frame for Gles2Frame {
|
|||
let damage = damage
|
||||
.iter()
|
||||
.map(|rect| {
|
||||
let src = src.size.to_f64();
|
||||
let rect = rect.to_f64();
|
||||
|
||||
let rect_constrained_loc = rect
|
||||
.loc
|
||||
.constrain(Rectangle::from_extemities((0f64, 0f64), dest.size.to_point()));
|
||||
let rect_clamped_size = rect.size.clamp(
|
||||
(0f64, 0f64),
|
||||
(dest.size.to_point() - rect_constrained_loc).to_size(),
|
||||
);
|
||||
.constrain(Rectangle::from_extemities((0f64, 0f64), src.to_point()));
|
||||
let rect_clamped_size = rect
|
||||
.size
|
||||
.clamp((0f64, 0f64), (src.to_point() - rect_constrained_loc).to_size());
|
||||
|
||||
let rect = Rectangle::from_loc_and_size(rect_constrained_loc, rect_clamped_size);
|
||||
let rect_transformed = self.transformation().transform_rect_in(rect, &dest.size);
|
||||
let rect_transformed = self.transformation().transform_rect_in(rect, &src);
|
||||
|
||||
[
|
||||
(rect_transformed.loc.x / dest.size.w) as f32,
|
||||
(rect_transformed.loc.y / dest.size.h) as f32,
|
||||
(rect_transformed.size.w / dest.size.w) as f32,
|
||||
(rect_transformed.size.h / dest.size.h) as f32,
|
||||
(rect_transformed.loc.x / src.w) as f32,
|
||||
(rect_transformed.loc.y / src.h) as f32,
|
||||
(rect_transformed.size.w / src.w) as f32,
|
||||
(rect_transformed.size.h / src.h) as f32,
|
||||
]
|
||||
})
|
||||
.flatten()
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
use std::collections::HashSet;
|
||||
use std::error::Error;
|
||||
|
||||
use crate::utils::{Buffer, Coordinate, Physical, Point, Rectangle, Size};
|
||||
use crate::utils::{Buffer, Physical, Point, Rectangle, Size, Transform};
|
||||
|
||||
#[cfg(feature = "wayland_frontend")]
|
||||
use crate::wayland::compositor::SurfaceData;
|
||||
|
@ -35,27 +35,6 @@ use crate::backend::egl::{
|
|||
#[cfg(feature = "wayland_frontend")]
|
||||
pub mod utils;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||
/// Possible transformations to two-dimensional planes
|
||||
pub enum Transform {
|
||||
/// Identity transformation (plane is unaltered when applied)
|
||||
Normal,
|
||||
/// Plane is rotated by 90 degrees
|
||||
_90,
|
||||
/// Plane is rotated by 180 degrees
|
||||
_180,
|
||||
/// Plane is rotated by 270 degrees
|
||||
_270,
|
||||
/// Plane is flipped vertically
|
||||
Flipped,
|
||||
/// Plane is flipped vertically and rotated by 90 degrees
|
||||
Flipped90,
|
||||
/// Plane is flipped vertically and rotated by 180 degrees
|
||||
Flipped180,
|
||||
/// Plane is flipped vertically and rotated by 270 degrees
|
||||
Flipped270,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||
/// Texture filtering methods
|
||||
pub enum TextureFilter {
|
||||
|
@ -74,70 +53,11 @@ impl Transform {
|
|||
Transform::_180 => Matrix3::new(-1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 1.0),
|
||||
Transform::_270 => Matrix3::new(0.0, 1.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 1.0),
|
||||
Transform::Flipped => Matrix3::new(-1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0),
|
||||
Transform::Flipped90 => Matrix3::new(0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0),
|
||||
Transform::Flipped90 => Matrix3::new(0.0, -1.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 1.0),
|
||||
Transform::Flipped180 => Matrix3::new(1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 1.0),
|
||||
Transform::Flipped270 => Matrix3::new(0.0, -1.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 1.0),
|
||||
Transform::Flipped270 => Matrix3::new(0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0),
|
||||
}
|
||||
}
|
||||
|
||||
/// Inverts any 90-degree transformation into 270-degree transformations and vise versa.
|
||||
///
|
||||
/// Flipping is preserved and 180/Normal transformation are uneffected.
|
||||
pub fn invert(&self) -> Transform {
|
||||
match self {
|
||||
Transform::Normal => Transform::Normal,
|
||||
Transform::Flipped => Transform::Flipped,
|
||||
Transform::_90 => Transform::_270,
|
||||
Transform::_180 => Transform::_180,
|
||||
Transform::_270 => Transform::_90,
|
||||
Transform::Flipped90 => Transform::Flipped270,
|
||||
Transform::Flipped180 => Transform::Flipped180,
|
||||
Transform::Flipped270 => Transform::Flipped90,
|
||||
}
|
||||
}
|
||||
|
||||
/// Transformed size after applying this transformation.
|
||||
pub fn transform_size<N: Coordinate, Kind>(&self, size: Size<N, Kind>) -> Size<N, Kind> {
|
||||
if *self == Transform::_90
|
||||
|| *self == Transform::_270
|
||||
|| *self == Transform::Flipped90
|
||||
|| *self == Transform::Flipped270
|
||||
{
|
||||
(size.h, size.w).into()
|
||||
} else {
|
||||
size
|
||||
}
|
||||
}
|
||||
|
||||
/// Transforms a rectangle inside an area of a given size by applying this transformation
|
||||
pub fn transform_rect_in<N: Coordinate, Kind>(
|
||||
&self,
|
||||
rect: Rectangle<N, Kind>,
|
||||
area: &Size<N, Kind>,
|
||||
) -> Rectangle<N, Kind> {
|
||||
let size = self.transform_size(rect.size);
|
||||
|
||||
let loc = match *self {
|
||||
Transform::Normal => rect.loc,
|
||||
Transform::_90 => (area.h - rect.loc.y - rect.size.h, rect.loc.x).into(),
|
||||
Transform::_180 => (
|
||||
area.w - rect.loc.x - rect.size.w,
|
||||
area.h - rect.loc.y - rect.size.h,
|
||||
)
|
||||
.into(),
|
||||
Transform::_270 => (rect.loc.y, area.w - rect.loc.x - rect.size.w).into(),
|
||||
Transform::Flipped => (area.w - rect.loc.x - rect.size.w, rect.loc.y).into(),
|
||||
Transform::Flipped90 => (rect.loc.y, rect.loc.x).into(),
|
||||
Transform::Flipped180 => (rect.loc.x, area.h - rect.loc.y - rect.size.h).into(),
|
||||
Transform::Flipped270 => (
|
||||
area.h - rect.loc.y - rect.size.h,
|
||||
area.w - rect.loc.x - rect.size.w,
|
||||
)
|
||||
.into(),
|
||||
};
|
||||
|
||||
Rectangle::from_loc_and_size(loc, size)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "wayland_frontend")]
|
||||
|
@ -217,7 +137,7 @@ pub trait Frame {
|
|||
texture_scale: i32,
|
||||
output_scale: f64,
|
||||
src_transform: Transform,
|
||||
damage: &[Rectangle<i32, Physical>],
|
||||
damage: &[Rectangle<i32, Buffer>],
|
||||
alpha: f32,
|
||||
) -> Result<(), Self::Error> {
|
||||
self.render_texture_from_to(
|
||||
|
@ -227,7 +147,7 @@ pub trait Frame {
|
|||
pos,
|
||||
texture
|
||||
.size()
|
||||
.to_logical(texture_scale)
|
||||
.to_logical(texture_scale, src_transform)
|
||||
.to_f64()
|
||||
.to_physical(output_scale),
|
||||
),
|
||||
|
@ -245,7 +165,7 @@ pub trait Frame {
|
|||
texture: &Self::TextureId,
|
||||
src: Rectangle<i32, Buffer>,
|
||||
dst: Rectangle<f64, Physical>,
|
||||
damage: &[Rectangle<i32, Physical>],
|
||||
damage: &[Rectangle<i32, Buffer>],
|
||||
src_transform: Transform,
|
||||
alpha: f32,
|
||||
) -> Result<(), Self::Error>;
|
||||
|
@ -540,7 +460,7 @@ pub fn buffer_type(buffer: &wl_buffer::WlBuffer) -> Option<BufferType> {
|
|||
///
|
||||
/// *Note*: This will only return dimensions for buffer types known to smithay (see [`buffer_type`])
|
||||
#[cfg(feature = "wayland_frontend")]
|
||||
pub fn buffer_dimensions(buffer: &wl_buffer::WlBuffer) -> Option<Size<i32, Physical>> {
|
||||
pub fn buffer_dimensions(buffer: &wl_buffer::WlBuffer) -> Option<Size<i32, Buffer>> {
|
||||
use crate::backend::allocator::Buffer;
|
||||
|
||||
if let Some(buf) = buffer.as_ref().user_data().get::<Dmabuf>() {
|
||||
|
@ -560,102 +480,3 @@ pub fn buffer_dimensions(buffer: &wl_buffer::WlBuffer) -> Option<Size<i32, Physi
|
|||
|
||||
crate::wayland::shm::with_buffer_contents(buffer, |_, data| (data.width, data.height).into()).ok()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Transform;
|
||||
use crate::utils::{Logical, Rectangle, Size};
|
||||
|
||||
#[test]
|
||||
fn transform_rect_ident() {
|
||||
let rect = Rectangle::<i32, Logical>::from_loc_and_size((10, 20), (30, 40));
|
||||
let size = Size::from((70, 90));
|
||||
let transform = Transform::Normal;
|
||||
|
||||
assert_eq!(rect, transform.transform_rect_in(rect, &size))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transform_rect_90() {
|
||||
let rect = Rectangle::<i32, Logical>::from_loc_and_size((10, 20), (30, 40));
|
||||
let size = Size::from((70, 90));
|
||||
let transform = Transform::_90;
|
||||
|
||||
assert_eq!(
|
||||
Rectangle::from_loc_and_size((30, 10), (40, 30)),
|
||||
transform.transform_rect_in(rect, &size)
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transform_rect_180() {
|
||||
let rect = Rectangle::<i32, Logical>::from_loc_and_size((10, 20), (30, 40));
|
||||
let size = Size::from((70, 90));
|
||||
let transform = Transform::_180;
|
||||
|
||||
assert_eq!(
|
||||
Rectangle::from_loc_and_size((30, 30), (30, 40)),
|
||||
transform.transform_rect_in(rect, &size)
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transform_rect_270() {
|
||||
let rect = Rectangle::<i32, Logical>::from_loc_and_size((10, 20), (30, 40));
|
||||
let size = Size::from((70, 90));
|
||||
let transform = Transform::_270;
|
||||
|
||||
assert_eq!(
|
||||
Rectangle::from_loc_and_size((20, 30), (40, 30)),
|
||||
transform.transform_rect_in(rect, &size)
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transform_rect_f() {
|
||||
let rect = Rectangle::<i32, Logical>::from_loc_and_size((10, 20), (30, 40));
|
||||
let size = Size::from((70, 90));
|
||||
let transform = Transform::Flipped;
|
||||
|
||||
assert_eq!(
|
||||
Rectangle::from_loc_and_size((30, 20), (30, 40)),
|
||||
transform.transform_rect_in(rect, &size)
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transform_rect_f90() {
|
||||
let rect = Rectangle::<i32, Logical>::from_loc_and_size((10, 20), (30, 40));
|
||||
let size = Size::from((70, 80));
|
||||
let transform = Transform::Flipped90;
|
||||
|
||||
assert_eq!(
|
||||
Rectangle::from_loc_and_size((20, 10), (40, 30)),
|
||||
transform.transform_rect_in(rect, &size)
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transform_rect_f180() {
|
||||
let rect = Rectangle::<i32, Logical>::from_loc_and_size((10, 20), (30, 40));
|
||||
let size = Size::from((70, 90));
|
||||
let transform = Transform::Flipped180;
|
||||
|
||||
assert_eq!(
|
||||
Rectangle::from_loc_and_size((10, 30), (30, 40)),
|
||||
transform.transform_rect_in(rect, &size)
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transform_rect_f270() {
|
||||
let rect = Rectangle::<i32, Logical>::from_loc_and_size((10, 20), (30, 40));
|
||||
let size = Size::from((70, 90));
|
||||
let transform = Transform::Flipped270;
|
||||
|
||||
assert_eq!(
|
||||
Rectangle::from_loc_and_size((30, 30), (40, 30)),
|
||||
transform.transform_rect_in(rect, &size)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use crate::{
|
||||
backend::renderer::{buffer_dimensions, Frame, ImportAll, Renderer, Texture},
|
||||
utils::{Logical, Physical, Point, Rectangle, Size},
|
||||
utils::{Buffer, Logical, Point, Rectangle, Size, Transform},
|
||||
wayland::compositor::{
|
||||
is_sync_subsurface, with_surface_tree_upward, BufferAssignment, Damage, SubsurfaceCachedState,
|
||||
SurfaceAttributes, TraversalAction,
|
||||
|
@ -15,8 +15,9 @@ use wayland_server::protocol::{wl_buffer::WlBuffer, wl_surface::WlSurface};
|
|||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct SurfaceState {
|
||||
pub(crate) buffer_dimensions: Option<Size<i32, Physical>>,
|
||||
pub(crate) buffer_dimensions: Option<Size<i32, Buffer>>,
|
||||
pub(crate) buffer_scale: i32,
|
||||
pub(crate) buffer_transform: Transform,
|
||||
pub(crate) buffer: Option<WlBuffer>,
|
||||
pub(crate) texture: Option<Box<dyn std::any::Any + 'static>>,
|
||||
#[cfg(feature = "desktop")]
|
||||
|
@ -30,6 +31,7 @@ impl SurfaceState {
|
|||
// new contents
|
||||
self.buffer_dimensions = buffer_dimensions(&buffer);
|
||||
self.buffer_scale = attrs.buffer_scale;
|
||||
self.buffer_transform = attrs.buffer_transform.into();
|
||||
if let Some(old_buffer) = std::mem::replace(&mut self.buffer, Some(buffer)) {
|
||||
if &old_buffer != self.buffer.as_ref().unwrap() {
|
||||
old_buffer.release();
|
||||
|
@ -52,6 +54,13 @@ impl SurfaceState {
|
|||
None => {}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the size of the surface.
|
||||
pub fn surface_size(&self) -> Option<Size<i32, Logical>> {
|
||||
self.buffer_dimensions
|
||||
.as_ref()
|
||||
.map(|dim| dim.to_logical(self.buffer_scale, self.buffer_transform))
|
||||
}
|
||||
}
|
||||
|
||||
/// Handler to let smithay take over buffer management.
|
||||
|
@ -110,10 +119,6 @@ where
|
|||
T: Texture + 'static,
|
||||
{
|
||||
let mut result = Ok(());
|
||||
let damage = damage
|
||||
.iter()
|
||||
.map(|geo| geo.to_f64().to_physical(scale).to_i32_up())
|
||||
.collect::<Vec<_>>();
|
||||
with_surface_tree_upward(
|
||||
surface,
|
||||
location,
|
||||
|
@ -125,17 +130,20 @@ where
|
|||
// Import a new buffer if necessary
|
||||
if data.texture.is_none() {
|
||||
if let Some(buffer) = data.buffer.as_ref() {
|
||||
let damage = attributes
|
||||
let buffer_damage = attributes
|
||||
.damage
|
||||
.iter()
|
||||
.map(|dmg| match dmg {
|
||||
Damage::Buffer(rect) => *rect,
|
||||
// TODO also apply transformations
|
||||
Damage::Surface(rect) => rect.to_buffer(attributes.buffer_scale),
|
||||
Damage::Surface(rect) => rect.to_buffer(
|
||||
attributes.buffer_scale,
|
||||
attributes.buffer_transform.into(),
|
||||
&data.surface_size().unwrap(),
|
||||
),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
match renderer.import_buffer(buffer, Some(states), &damage) {
|
||||
match renderer.import_buffer(buffer, Some(states), &buffer_damage) {
|
||||
Some(Ok(m)) => {
|
||||
data.texture = Some(Box::new(m));
|
||||
}
|
||||
|
@ -169,10 +177,12 @@ where
|
|||
let mut location = *location;
|
||||
if let Some(data) = states.data_map.get::<RefCell<SurfaceState>>() {
|
||||
let mut data = data.borrow_mut();
|
||||
let dimensions = data.surface_size();
|
||||
let buffer_scale = data.buffer_scale;
|
||||
let buffer_dimensions = data.buffer_dimensions;
|
||||
let buffer_transform = data.buffer_transform;
|
||||
let attributes = states.cached_state.current::<SurfaceAttributes>();
|
||||
if let Some(texture) = data.texture.as_mut().and_then(|x| x.downcast_mut::<T>()) {
|
||||
let dimensions = dimensions.unwrap();
|
||||
// we need to re-extract the subsurface offset, as the previous closure
|
||||
// only passes it to our children
|
||||
let mut surface_offset = (0, 0).into();
|
||||
|
@ -182,23 +192,19 @@ where
|
|||
location += current.location;
|
||||
}
|
||||
|
||||
let rect = Rectangle::<i32, Physical>::from_loc_and_size(
|
||||
surface_offset.to_f64().to_physical(scale).to_i32_round(),
|
||||
buffer_dimensions
|
||||
.unwrap_or_default()
|
||||
.to_logical(buffer_scale)
|
||||
.to_f64()
|
||||
.to_physical(scale)
|
||||
.to_i32_round(),
|
||||
);
|
||||
let new_damage = damage
|
||||
let damage = damage
|
||||
.iter()
|
||||
.cloned()
|
||||
.flat_map(|geo| geo.intersection(rect))
|
||||
// first move the damage by the surface offset in logical space
|
||||
.map(|mut geo| {
|
||||
geo.loc -= rect.loc;
|
||||
// make the damage relative to the surfaec
|
||||
geo.loc -= surface_offset;
|
||||
geo
|
||||
})
|
||||
// then clamp to surface size again in logical space
|
||||
.flat_map(|geo| geo.intersection(Rectangle::from_loc_and_size((0, 0), dimensions)))
|
||||
// lastly transform it into buffer space
|
||||
.map(|geo| geo.to_buffer(buffer_scale, buffer_transform, &dimensions))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// TODO: Take wp_viewporter into account
|
||||
|
@ -208,7 +214,7 @@ where
|
|||
buffer_scale,
|
||||
scale,
|
||||
attributes.buffer_transform.into(),
|
||||
&new_damage,
|
||||
&damage,
|
||||
1.0,
|
||||
) {
|
||||
result = Err(err);
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
//! rendering helpers to add custom elements or different clients to a space.
|
||||
|
||||
use crate::{
|
||||
backend::renderer::{utils::SurfaceState, Frame, ImportAll, Renderer, Transform},
|
||||
backend::renderer::{utils::SurfaceState, Frame, ImportAll, Renderer},
|
||||
desktop::{
|
||||
layer::{layer_map_for_output, LayerSurface},
|
||||
window::Window,
|
||||
},
|
||||
utils::{Logical, Point, Rectangle},
|
||||
utils::{Logical, Point, Rectangle, Transform},
|
||||
wayland::{
|
||||
compositor::{
|
||||
get_parent, is_sync_subsurface, with_surface_tree_downward, SubsurfaceCachedState,
|
||||
|
@ -372,7 +372,7 @@ impl Space {
|
|||
|wl_surface, states, &loc| {
|
||||
let data = states.data_map.get::<RefCell<SurfaceState>>();
|
||||
|
||||
if let Some(size) = data.and_then(|d| d.borrow().size()) {
|
||||
if let Some(size) = data.and_then(|d| d.borrow().surface_size()) {
|
||||
let surface_rectangle = Rectangle { loc, size };
|
||||
|
||||
if output_geometry.overlaps(surface_rectangle) {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use crate::{
|
||||
backend::renderer::utils::SurfaceState,
|
||||
desktop::Space,
|
||||
utils::{Logical, Point, Rectangle, Size},
|
||||
utils::{Logical, Point, Rectangle},
|
||||
wayland::{
|
||||
compositor::{
|
||||
with_surface_tree_downward, with_surface_tree_upward, Damage, SubsurfaceCachedState,
|
||||
|
@ -17,15 +17,9 @@ 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<P: Into<Point<f64, Logical>>>(&self, attrs: &SurfaceAttributes, point: P) -> bool {
|
||||
let point = point.into();
|
||||
let size = match self.size() {
|
||||
let size = match self.surface_size() {
|
||||
None => return false, // If the surface has no size, it can't have an input region.
|
||||
Some(size) => size,
|
||||
};
|
||||
|
@ -71,7 +65,7 @@ where
|
|||
let mut loc = *loc;
|
||||
let data = states.data_map.get::<RefCell<SurfaceState>>();
|
||||
|
||||
if let Some(size) = data.and_then(|d| d.borrow().size()) {
|
||||
if let Some(size) = data.and_then(|d| d.borrow().surface_size()) {
|
||||
if states.role == Some("subsurface") {
|
||||
let current = states.cached_state.current::<SubsurfaceCachedState>();
|
||||
loc += current.location;
|
||||
|
@ -148,7 +142,11 @@ where
|
|||
|
||||
damage.extend(attributes.damage.iter().map(|dmg| {
|
||||
let mut rect = match dmg {
|
||||
Damage::Buffer(rect) => rect.to_logical(attributes.buffer_scale),
|
||||
Damage::Buffer(rect) => rect.to_logical(
|
||||
attributes.buffer_scale,
|
||||
attributes.buffer_transform.into(),
|
||||
&data.buffer_dimensions.unwrap(),
|
||||
),
|
||||
Damage::Surface(rect) => *rect,
|
||||
};
|
||||
rect.loc += location;
|
||||
|
|
|
@ -406,10 +406,11 @@ impl<N: Coordinate> Point<N, Logical> {
|
|||
|
||||
#[inline]
|
||||
/// Convert this logical point to buffer coordinate space according to given scale factor
|
||||
pub fn to_buffer(self, scale: N) -> Point<N, Buffer> {
|
||||
pub fn to_buffer(self, scale: N, transformation: Transform, area: &Size<N, Logical>) -> Point<N, Buffer> {
|
||||
let point = transformation.transform_point_in(self, area);
|
||||
Point {
|
||||
x: self.x.upscale(scale),
|
||||
y: self.y.upscale(scale),
|
||||
x: point.x.upscale(scale),
|
||||
y: point.y.upscale(scale),
|
||||
_kind: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
@ -430,10 +431,11 @@ impl<N: Coordinate> Point<N, Physical> {
|
|||
impl<N: Coordinate> Point<N, Buffer> {
|
||||
#[inline]
|
||||
/// Convert this physical point to logical coordinate space according to given scale factor
|
||||
pub fn to_logical(self, scale: N) -> Point<N, Logical> {
|
||||
pub fn to_logical(self, scale: N, transform: Transform, area: &Size<N, Buffer>) -> Point<N, Logical> {
|
||||
let point = transform.invert().transform_point_in(self, area);
|
||||
Point {
|
||||
x: self.x.downscale(scale),
|
||||
y: self.y.downscale(scale),
|
||||
x: point.x.downscale(scale),
|
||||
y: point.y.downscale(scale),
|
||||
_kind: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
@ -667,12 +669,12 @@ impl<N: Coordinate> Size<N, Logical> {
|
|||
|
||||
#[inline]
|
||||
/// Convert this logical size to buffer coordinate space according to given scale factor
|
||||
pub fn to_buffer(self, scale: N) -> Size<N, Buffer> {
|
||||
Size {
|
||||
pub fn to_buffer(self, scale: N, transformation: Transform) -> Size<N, Buffer> {
|
||||
transformation.transform_size(Size {
|
||||
w: self.w.upscale(scale),
|
||||
h: self.h.upscale(scale),
|
||||
_kind: std::marker::PhantomData,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -691,12 +693,12 @@ impl<N: Coordinate> Size<N, Physical> {
|
|||
impl<N: Coordinate> Size<N, Buffer> {
|
||||
#[inline]
|
||||
/// Convert this physical point to logical coordinate space according to given scale factor
|
||||
pub fn to_logical(self, scale: N) -> Size<N, Logical> {
|
||||
Size {
|
||||
pub fn to_logical(self, scale: N, transformation: Transform) -> Size<N, Logical> {
|
||||
transformation.invert().transform_size(Size {
|
||||
w: self.w.downscale(scale),
|
||||
h: self.h.downscale(scale),
|
||||
_kind: std::marker::PhantomData,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -969,10 +971,24 @@ impl<N: Coordinate> Rectangle<N, Logical> {
|
|||
|
||||
/// Convert this logical rectangle to buffer coordinate space according to given scale factor
|
||||
#[inline]
|
||||
pub fn to_buffer(self, scale: N) -> Rectangle<N, Buffer> {
|
||||
pub fn to_buffer(
|
||||
self,
|
||||
scale: N,
|
||||
transformation: Transform,
|
||||
area: &Size<N, Logical>,
|
||||
) -> Rectangle<N, Buffer> {
|
||||
let rect = transformation.transform_rect_in(self, area);
|
||||
Rectangle {
|
||||
loc: self.loc.to_buffer(scale),
|
||||
size: self.size.to_buffer(scale),
|
||||
loc: Point {
|
||||
x: rect.loc.x.upscale(scale),
|
||||
y: rect.loc.y.upscale(scale),
|
||||
_kind: std::marker::PhantomData,
|
||||
},
|
||||
size: Size {
|
||||
w: rect.size.w.upscale(scale),
|
||||
h: rect.size.h.upscale(scale),
|
||||
_kind: std::marker::PhantomData,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -991,10 +1007,24 @@ impl<N: Coordinate> Rectangle<N, Physical> {
|
|||
impl<N: Coordinate> Rectangle<N, Buffer> {
|
||||
/// Convert this physical rectangle to logical coordinate space according to given scale factor
|
||||
#[inline]
|
||||
pub fn to_logical(self, scale: N) -> Rectangle<N, Logical> {
|
||||
pub fn to_logical(
|
||||
self,
|
||||
scale: N,
|
||||
transformation: Transform,
|
||||
area: &Size<N, Buffer>,
|
||||
) -> Rectangle<N, Logical> {
|
||||
let rect = transformation.invert().transform_rect_in(self, area);
|
||||
Rectangle {
|
||||
loc: self.loc.to_logical(scale),
|
||||
size: self.size.to_logical(scale),
|
||||
loc: Point {
|
||||
x: rect.loc.x.downscale(scale),
|
||||
y: rect.loc.y.downscale(scale),
|
||||
_kind: std::marker::PhantomData,
|
||||
},
|
||||
size: Size {
|
||||
w: rect.size.w.downscale(scale),
|
||||
h: rect.size.h.downscale(scale),
|
||||
_kind: std::marker::PhantomData,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1071,3 +1101,207 @@ impl<N: Default, Kind> Default for Rectangle<N, Kind> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||
/// Possible transformations to two-dimensional planes
|
||||
pub enum Transform {
|
||||
/// Identity transformation (plane is unaltered when applied)
|
||||
Normal,
|
||||
/// Plane is rotated by 90 degrees
|
||||
_90,
|
||||
/// Plane is rotated by 180 degrees
|
||||
_180,
|
||||
/// Plane is rotated by 270 degrees
|
||||
_270,
|
||||
/// Plane is flipped vertically
|
||||
Flipped,
|
||||
/// Plane is flipped vertically and rotated by 90 degrees
|
||||
Flipped90,
|
||||
/// Plane is flipped vertically and rotated by 180 degrees
|
||||
Flipped180,
|
||||
/// Plane is flipped vertically and rotated by 270 degrees
|
||||
Flipped270,
|
||||
}
|
||||
|
||||
impl Default for Transform {
|
||||
fn default() -> Transform {
|
||||
Transform::Normal
|
||||
}
|
||||
}
|
||||
|
||||
impl Transform {
|
||||
/// Inverts any 90-degree transformation into 270-degree transformations and vise versa.
|
||||
///
|
||||
/// Flipping is preserved and 180/Normal transformation are uneffected.
|
||||
pub fn invert(&self) -> Transform {
|
||||
match self {
|
||||
Transform::Normal => Transform::Normal,
|
||||
Transform::Flipped => Transform::Flipped,
|
||||
Transform::_90 => Transform::_270,
|
||||
Transform::_180 => Transform::_180,
|
||||
Transform::_270 => Transform::_90,
|
||||
Transform::Flipped90 => Transform::Flipped270,
|
||||
Transform::Flipped180 => Transform::Flipped180,
|
||||
Transform::Flipped270 => Transform::Flipped90,
|
||||
}
|
||||
}
|
||||
|
||||
/// Transforms a point inside an area of a given size by applying this transformation.
|
||||
pub fn transform_point_in<N: Coordinate, Kind>(
|
||||
&self,
|
||||
point: Point<N, Kind>,
|
||||
area: &Size<N, Kind>,
|
||||
) -> Point<N, Kind> {
|
||||
match *self {
|
||||
Transform::Normal => point,
|
||||
Transform::_90 => (area.h - point.y, point.x).into(),
|
||||
Transform::_180 => (area.w - point.x, area.h - point.y).into(),
|
||||
Transform::_270 => (point.y, area.w - point.x).into(),
|
||||
Transform::Flipped => (area.w - point.x, point.y).into(),
|
||||
Transform::Flipped90 => (point.y, point.x).into(),
|
||||
Transform::Flipped180 => (point.x, area.h - point.y).into(),
|
||||
Transform::Flipped270 => (area.h - point.y, area.w - point.x).into(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Transformed size after applying this transformation.
|
||||
pub fn transform_size<N: Coordinate, Kind>(&self, size: Size<N, Kind>) -> Size<N, Kind> {
|
||||
if *self == Transform::_90
|
||||
|| *self == Transform::_270
|
||||
|| *self == Transform::Flipped90
|
||||
|| *self == Transform::Flipped270
|
||||
{
|
||||
(size.h, size.w).into()
|
||||
} else {
|
||||
size
|
||||
}
|
||||
}
|
||||
|
||||
/// Transforms a rectangle inside an area of a given size by applying this transformation.
|
||||
pub fn transform_rect_in<N: Coordinate, Kind>(
|
||||
&self,
|
||||
rect: Rectangle<N, Kind>,
|
||||
area: &Size<N, Kind>,
|
||||
) -> Rectangle<N, Kind> {
|
||||
let size = self.transform_size(rect.size);
|
||||
|
||||
let loc = match *self {
|
||||
Transform::Normal => rect.loc,
|
||||
Transform::_90 => (area.h - rect.loc.y - rect.size.h, rect.loc.x).into(),
|
||||
Transform::_180 => (
|
||||
area.w - rect.loc.x - rect.size.w,
|
||||
area.h - rect.loc.y - rect.size.h,
|
||||
)
|
||||
.into(),
|
||||
Transform::_270 => (rect.loc.y, area.w - rect.loc.x - rect.size.w).into(),
|
||||
Transform::Flipped => (area.w - rect.loc.x - rect.size.w, rect.loc.y).into(),
|
||||
Transform::Flipped90 => (rect.loc.y, rect.loc.x).into(),
|
||||
Transform::Flipped180 => (rect.loc.x, area.h - rect.loc.y - rect.size.h).into(),
|
||||
Transform::Flipped270 => (
|
||||
area.h - rect.loc.y - rect.size.h,
|
||||
area.w - rect.loc.x - rect.size.w,
|
||||
)
|
||||
.into(),
|
||||
};
|
||||
|
||||
Rectangle::from_loc_and_size(loc, size)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{Logical, Rectangle, Size, Transform};
|
||||
|
||||
#[test]
|
||||
fn transform_rect_ident() {
|
||||
let rect = Rectangle::<i32, Logical>::from_loc_and_size((10, 20), (30, 40));
|
||||
let size = Size::from((70, 90));
|
||||
let transform = Transform::Normal;
|
||||
|
||||
assert_eq!(rect, transform.transform_rect_in(rect, &size))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transform_rect_90() {
|
||||
let rect = Rectangle::<i32, Logical>::from_loc_and_size((10, 20), (30, 40));
|
||||
let size = Size::from((70, 90));
|
||||
let transform = Transform::_90;
|
||||
|
||||
assert_eq!(
|
||||
Rectangle::from_loc_and_size((30, 10), (40, 30)),
|
||||
transform.transform_rect_in(rect, &size)
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transform_rect_180() {
|
||||
let rect = Rectangle::<i32, Logical>::from_loc_and_size((10, 20), (30, 40));
|
||||
let size = Size::from((70, 90));
|
||||
let transform = Transform::_180;
|
||||
|
||||
assert_eq!(
|
||||
Rectangle::from_loc_and_size((30, 30), (30, 40)),
|
||||
transform.transform_rect_in(rect, &size)
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transform_rect_270() {
|
||||
let rect = Rectangle::<i32, Logical>::from_loc_and_size((10, 20), (30, 40));
|
||||
let size = Size::from((70, 90));
|
||||
let transform = Transform::_270;
|
||||
|
||||
assert_eq!(
|
||||
Rectangle::from_loc_and_size((20, 30), (40, 30)),
|
||||
transform.transform_rect_in(rect, &size)
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transform_rect_f() {
|
||||
let rect = Rectangle::<i32, Logical>::from_loc_and_size((10, 20), (30, 40));
|
||||
let size = Size::from((70, 90));
|
||||
let transform = Transform::Flipped;
|
||||
|
||||
assert_eq!(
|
||||
Rectangle::from_loc_and_size((30, 20), (30, 40)),
|
||||
transform.transform_rect_in(rect, &size)
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transform_rect_f90() {
|
||||
let rect = Rectangle::<i32, Logical>::from_loc_and_size((10, 20), (30, 40));
|
||||
let size = Size::from((70, 80));
|
||||
let transform = Transform::Flipped90;
|
||||
|
||||
assert_eq!(
|
||||
Rectangle::from_loc_and_size((20, 10), (40, 30)),
|
||||
transform.transform_rect_in(rect, &size)
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transform_rect_f180() {
|
||||
let rect = Rectangle::<i32, Logical>::from_loc_and_size((10, 20), (30, 40));
|
||||
let size = Size::from((70, 90));
|
||||
let transform = Transform::Flipped180;
|
||||
|
||||
assert_eq!(
|
||||
Rectangle::from_loc_and_size((10, 30), (30, 40)),
|
||||
transform.transform_rect_in(rect, &size)
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transform_rect_f270() {
|
||||
let rect = Rectangle::<i32, Logical>::from_loc_and_size((10, 20), (30, 40));
|
||||
let size = Size::from((70, 90));
|
||||
let transform = Transform::Flipped270;
|
||||
|
||||
assert_eq!(
|
||||
Rectangle::from_loc_and_size((30, 30), (40, 30)),
|
||||
transform.transform_rect_in(rect, &size)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ pub mod x11rb;
|
|||
pub(crate) mod ids;
|
||||
pub mod user_data;
|
||||
|
||||
pub use self::geometry::{Buffer, Coordinate, Logical, Physical, Point, Raw, Rectangle, Size};
|
||||
pub use self::geometry::{Buffer, Coordinate, Logical, Physical, Point, Raw, Rectangle, Size, Transform};
|
||||
|
||||
/// This resource is not managed by Smithay
|
||||
#[derive(Debug)]
|
||||
|
|
Loading…
Reference in New Issue