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(
|
pub fn egl_buffer_dimensions(
|
||||||
&self,
|
&self,
|
||||||
buffer: &WlBuffer,
|
buffer: &WlBuffer,
|
||||||
) -> Option<crate::utils::Size<i32, crate::utils::Physical>> {
|
) -> Option<crate::utils::Size<i32, crate::utils::Buffer>> {
|
||||||
if !buffer.as_ref().is_alive() {
|
if !buffer.as_ref().is_alive() {
|
||||||
debug!(self.logger, "Suplied buffer is no longer alive");
|
debug!(self.logger, "Suplied buffer is no longer alive");
|
||||||
return None;
|
return None;
|
||||||
|
|
|
@ -13,7 +13,7 @@ use cgmath::{prelude::*, Matrix3, Vector2, Vector3};
|
||||||
mod shaders;
|
mod shaders;
|
||||||
mod version;
|
mod version;
|
||||||
|
|
||||||
use super::{Bind, Frame, Renderer, Texture, TextureFilter, Transform, Unbind};
|
use super::{Bind, Frame, Renderer, Texture, TextureFilter, Unbind};
|
||||||
use crate::backend::allocator::{
|
use crate::backend::allocator::{
|
||||||
dmabuf::{Dmabuf, WeakDmabuf},
|
dmabuf::{Dmabuf, WeakDmabuf},
|
||||||
Format,
|
Format,
|
||||||
|
@ -23,7 +23,7 @@ use crate::backend::egl::{
|
||||||
EGLContext, EGLSurface, MakeCurrentError,
|
EGLContext, EGLSurface, MakeCurrentError,
|
||||||
};
|
};
|
||||||
use crate::backend::SwapBuffersError;
|
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"))]
|
#[cfg(all(feature = "wayland_frontend", feature = "use_system_lib"))]
|
||||||
use super::ImportEgl;
|
use super::ImportEgl;
|
||||||
|
@ -1250,7 +1250,7 @@ impl Frame for Gles2Frame {
|
||||||
texture: &Self::TextureId,
|
texture: &Self::TextureId,
|
||||||
src: Rectangle<i32, Buffer>,
|
src: Rectangle<i32, Buffer>,
|
||||||
dest: Rectangle<f64, Physical>,
|
dest: Rectangle<f64, Physical>,
|
||||||
damage: &[Rectangle<i32, Physical>],
|
damage: &[Rectangle<i32, Buffer>],
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
alpha: f32,
|
alpha: f32,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
|
@ -1266,7 +1266,7 @@ impl Frame for Gles2Frame {
|
||||||
assert_eq!(mat, mat * transform.invert().matrix());
|
assert_eq!(mat, mat * transform.invert().matrix());
|
||||||
assert_eq!(transform.matrix(), Matrix3::<f32>::identity());
|
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));
|
mat = mat * Matrix3::from_translation(Vector2::new(-0.5, -0.5));
|
||||||
|
|
||||||
// this matrix should be regular, we can expect invert to succeed
|
// this matrix should be regular, we can expect invert to succeed
|
||||||
|
@ -1290,24 +1290,24 @@ impl Frame for Gles2Frame {
|
||||||
let damage = damage
|
let damage = damage
|
||||||
.iter()
|
.iter()
|
||||||
.map(|rect| {
|
.map(|rect| {
|
||||||
|
let src = src.size.to_f64();
|
||||||
let rect = rect.to_f64();
|
let rect = rect.to_f64();
|
||||||
|
|
||||||
let rect_constrained_loc = rect
|
let rect_constrained_loc = rect
|
||||||
.loc
|
.loc
|
||||||
.constrain(Rectangle::from_extemities((0f64, 0f64), dest.size.to_point()));
|
.constrain(Rectangle::from_extemities((0f64, 0f64), src.to_point()));
|
||||||
let rect_clamped_size = rect.size.clamp(
|
let rect_clamped_size = rect
|
||||||
(0f64, 0f64),
|
.size
|
||||||
(dest.size.to_point() - rect_constrained_loc).to_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 = 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.x / src.w) as f32,
|
||||||
(rect_transformed.loc.y / dest.size.h) as f32,
|
(rect_transformed.loc.y / src.h) as f32,
|
||||||
(rect_transformed.size.w / dest.size.w) as f32,
|
(rect_transformed.size.w / src.w) as f32,
|
||||||
(rect_transformed.size.h / dest.size.h) as f32,
|
(rect_transformed.size.h / src.h) as f32,
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
.flatten()
|
.flatten()
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::error::Error;
|
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")]
|
#[cfg(feature = "wayland_frontend")]
|
||||||
use crate::wayland::compositor::SurfaceData;
|
use crate::wayland::compositor::SurfaceData;
|
||||||
|
@ -35,27 +35,6 @@ use crate::backend::egl::{
|
||||||
#[cfg(feature = "wayland_frontend")]
|
#[cfg(feature = "wayland_frontend")]
|
||||||
pub mod utils;
|
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)]
|
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||||
/// Texture filtering methods
|
/// Texture filtering methods
|
||||||
pub enum TextureFilter {
|
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::_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::_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::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::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")]
|
#[cfg(feature = "wayland_frontend")]
|
||||||
|
@ -217,7 +137,7 @@ pub trait Frame {
|
||||||
texture_scale: i32,
|
texture_scale: i32,
|
||||||
output_scale: f64,
|
output_scale: f64,
|
||||||
src_transform: Transform,
|
src_transform: Transform,
|
||||||
damage: &[Rectangle<i32, Physical>],
|
damage: &[Rectangle<i32, Buffer>],
|
||||||
alpha: f32,
|
alpha: f32,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
self.render_texture_from_to(
|
self.render_texture_from_to(
|
||||||
|
@ -227,7 +147,7 @@ pub trait Frame {
|
||||||
pos,
|
pos,
|
||||||
texture
|
texture
|
||||||
.size()
|
.size()
|
||||||
.to_logical(texture_scale)
|
.to_logical(texture_scale, src_transform)
|
||||||
.to_f64()
|
.to_f64()
|
||||||
.to_physical(output_scale),
|
.to_physical(output_scale),
|
||||||
),
|
),
|
||||||
|
@ -245,7 +165,7 @@ pub trait Frame {
|
||||||
texture: &Self::TextureId,
|
texture: &Self::TextureId,
|
||||||
src: Rectangle<i32, Buffer>,
|
src: Rectangle<i32, Buffer>,
|
||||||
dst: Rectangle<f64, Physical>,
|
dst: Rectangle<f64, Physical>,
|
||||||
damage: &[Rectangle<i32, Physical>],
|
damage: &[Rectangle<i32, Buffer>],
|
||||||
src_transform: Transform,
|
src_transform: Transform,
|
||||||
alpha: f32,
|
alpha: f32,
|
||||||
) -> Result<(), Self::Error>;
|
) -> 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`])
|
/// *Note*: This will only return dimensions for buffer types known to smithay (see [`buffer_type`])
|
||||||
#[cfg(feature = "wayland_frontend")]
|
#[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;
|
use crate::backend::allocator::Buffer;
|
||||||
|
|
||||||
if let Some(buf) = buffer.as_ref().user_data().get::<Dmabuf>() {
|
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()
|
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::{
|
use crate::{
|
||||||
backend::renderer::{buffer_dimensions, Frame, ImportAll, Renderer, Texture},
|
backend::renderer::{buffer_dimensions, Frame, ImportAll, Renderer, Texture},
|
||||||
utils::{Logical, Physical, Point, Rectangle, Size},
|
utils::{Buffer, Logical, Point, Rectangle, Size, Transform},
|
||||||
wayland::compositor::{
|
wayland::compositor::{
|
||||||
is_sync_subsurface, with_surface_tree_upward, BufferAssignment, Damage, SubsurfaceCachedState,
|
is_sync_subsurface, with_surface_tree_upward, BufferAssignment, Damage, SubsurfaceCachedState,
|
||||||
SurfaceAttributes, TraversalAction,
|
SurfaceAttributes, TraversalAction,
|
||||||
|
@ -15,8 +15,9 @@ use wayland_server::protocol::{wl_buffer::WlBuffer, wl_surface::WlSurface};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub(crate) struct SurfaceState {
|
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_scale: i32,
|
||||||
|
pub(crate) buffer_transform: Transform,
|
||||||
pub(crate) buffer: Option<WlBuffer>,
|
pub(crate) buffer: Option<WlBuffer>,
|
||||||
pub(crate) texture: Option<Box<dyn std::any::Any + 'static>>,
|
pub(crate) texture: Option<Box<dyn std::any::Any + 'static>>,
|
||||||
#[cfg(feature = "desktop")]
|
#[cfg(feature = "desktop")]
|
||||||
|
@ -30,6 +31,7 @@ impl SurfaceState {
|
||||||
// new contents
|
// new contents
|
||||||
self.buffer_dimensions = buffer_dimensions(&buffer);
|
self.buffer_dimensions = buffer_dimensions(&buffer);
|
||||||
self.buffer_scale = attrs.buffer_scale;
|
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 let Some(old_buffer) = std::mem::replace(&mut self.buffer, Some(buffer)) {
|
||||||
if &old_buffer != self.buffer.as_ref().unwrap() {
|
if &old_buffer != self.buffer.as_ref().unwrap() {
|
||||||
old_buffer.release();
|
old_buffer.release();
|
||||||
|
@ -52,6 +54,13 @@ impl SurfaceState {
|
||||||
None => {}
|
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.
|
/// Handler to let smithay take over buffer management.
|
||||||
|
@ -110,10 +119,6 @@ where
|
||||||
T: Texture + 'static,
|
T: Texture + 'static,
|
||||||
{
|
{
|
||||||
let mut result = Ok(());
|
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(
|
with_surface_tree_upward(
|
||||||
surface,
|
surface,
|
||||||
location,
|
location,
|
||||||
|
@ -125,17 +130,20 @@ where
|
||||||
// Import a new buffer if necessary
|
// Import a new buffer if necessary
|
||||||
if data.texture.is_none() {
|
if data.texture.is_none() {
|
||||||
if let Some(buffer) = data.buffer.as_ref() {
|
if let Some(buffer) = data.buffer.as_ref() {
|
||||||
let damage = attributes
|
let buffer_damage = attributes
|
||||||
.damage
|
.damage
|
||||||
.iter()
|
.iter()
|
||||||
.map(|dmg| match dmg {
|
.map(|dmg| match dmg {
|
||||||
Damage::Buffer(rect) => *rect,
|
Damage::Buffer(rect) => *rect,
|
||||||
// TODO also apply transformations
|
Damage::Surface(rect) => rect.to_buffer(
|
||||||
Damage::Surface(rect) => rect.to_buffer(attributes.buffer_scale),
|
attributes.buffer_scale,
|
||||||
|
attributes.buffer_transform.into(),
|
||||||
|
&data.surface_size().unwrap(),
|
||||||
|
),
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
match renderer.import_buffer(buffer, Some(states), &damage) {
|
match renderer.import_buffer(buffer, Some(states), &buffer_damage) {
|
||||||
Some(Ok(m)) => {
|
Some(Ok(m)) => {
|
||||||
data.texture = Some(Box::new(m));
|
data.texture = Some(Box::new(m));
|
||||||
}
|
}
|
||||||
|
@ -169,10 +177,12 @@ where
|
||||||
let mut location = *location;
|
let mut location = *location;
|
||||||
if let Some(data) = states.data_map.get::<RefCell<SurfaceState>>() {
|
if let Some(data) = states.data_map.get::<RefCell<SurfaceState>>() {
|
||||||
let mut data = data.borrow_mut();
|
let mut data = data.borrow_mut();
|
||||||
|
let dimensions = data.surface_size();
|
||||||
let buffer_scale = data.buffer_scale;
|
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>();
|
let attributes = states.cached_state.current::<SurfaceAttributes>();
|
||||||
if let Some(texture) = data.texture.as_mut().and_then(|x| x.downcast_mut::<T>()) {
|
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
|
// we need to re-extract the subsurface offset, as the previous closure
|
||||||
// only passes it to our children
|
// only passes it to our children
|
||||||
let mut surface_offset = (0, 0).into();
|
let mut surface_offset = (0, 0).into();
|
||||||
|
@ -182,23 +192,19 @@ where
|
||||||
location += current.location;
|
location += current.location;
|
||||||
}
|
}
|
||||||
|
|
||||||
let rect = Rectangle::<i32, Physical>::from_loc_and_size(
|
let damage = damage
|
||||||
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
|
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
.flat_map(|geo| geo.intersection(rect))
|
// first move the damage by the surface offset in logical space
|
||||||
.map(|mut geo| {
|
.map(|mut geo| {
|
||||||
geo.loc -= rect.loc;
|
// make the damage relative to the surfaec
|
||||||
|
geo.loc -= surface_offset;
|
||||||
geo
|
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<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
// TODO: Take wp_viewporter into account
|
// TODO: Take wp_viewporter into account
|
||||||
|
@ -208,7 +214,7 @@ where
|
||||||
buffer_scale,
|
buffer_scale,
|
||||||
scale,
|
scale,
|
||||||
attributes.buffer_transform.into(),
|
attributes.buffer_transform.into(),
|
||||||
&new_damage,
|
&damage,
|
||||||
1.0,
|
1.0,
|
||||||
) {
|
) {
|
||||||
result = Err(err);
|
result = Err(err);
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
//! rendering helpers to add custom elements or different clients to a space.
|
//! rendering helpers to add custom elements or different clients to a space.
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::renderer::{utils::SurfaceState, Frame, ImportAll, Renderer, Transform},
|
backend::renderer::{utils::SurfaceState, Frame, ImportAll, Renderer},
|
||||||
desktop::{
|
desktop::{
|
||||||
layer::{layer_map_for_output, LayerSurface},
|
layer::{layer_map_for_output, LayerSurface},
|
||||||
window::Window,
|
window::Window,
|
||||||
},
|
},
|
||||||
utils::{Logical, Point, Rectangle},
|
utils::{Logical, Point, Rectangle, Transform},
|
||||||
wayland::{
|
wayland::{
|
||||||
compositor::{
|
compositor::{
|
||||||
get_parent, is_sync_subsurface, with_surface_tree_downward, SubsurfaceCachedState,
|
get_parent, is_sync_subsurface, with_surface_tree_downward, SubsurfaceCachedState,
|
||||||
|
@ -372,7 +372,7 @@ impl Space {
|
||||||
|wl_surface, states, &loc| {
|
|wl_surface, states, &loc| {
|
||||||
let data = states.data_map.get::<RefCell<SurfaceState>>();
|
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 };
|
let surface_rectangle = Rectangle { loc, size };
|
||||||
|
|
||||||
if output_geometry.overlaps(surface_rectangle) {
|
if output_geometry.overlaps(surface_rectangle) {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::renderer::utils::SurfaceState,
|
backend::renderer::utils::SurfaceState,
|
||||||
desktop::Space,
|
desktop::Space,
|
||||||
utils::{Logical, Point, Rectangle, Size},
|
utils::{Logical, Point, Rectangle},
|
||||||
wayland::{
|
wayland::{
|
||||||
compositor::{
|
compositor::{
|
||||||
with_surface_tree_downward, with_surface_tree_upward, Damage, SubsurfaceCachedState,
|
with_surface_tree_downward, with_surface_tree_upward, Damage, SubsurfaceCachedState,
|
||||||
|
@ -17,15 +17,9 @@ use wayland_server::protocol::wl_surface;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
|
||||||
impl SurfaceState {
|
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 {
|
fn contains_point<P: Into<Point<f64, Logical>>>(&self, attrs: &SurfaceAttributes, point: P) -> bool {
|
||||||
let point = point.into();
|
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.
|
None => return false, // If the surface has no size, it can't have an input region.
|
||||||
Some(size) => size,
|
Some(size) => size,
|
||||||
};
|
};
|
||||||
|
@ -71,7 +65,7 @@ where
|
||||||
let mut loc = *loc;
|
let mut loc = *loc;
|
||||||
let data = states.data_map.get::<RefCell<SurfaceState>>();
|
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") {
|
if states.role == Some("subsurface") {
|
||||||
let current = states.cached_state.current::<SubsurfaceCachedState>();
|
let current = states.cached_state.current::<SubsurfaceCachedState>();
|
||||||
loc += current.location;
|
loc += current.location;
|
||||||
|
@ -148,7 +142,11 @@ where
|
||||||
|
|
||||||
damage.extend(attributes.damage.iter().map(|dmg| {
|
damage.extend(attributes.damage.iter().map(|dmg| {
|
||||||
let mut rect = match 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,
|
Damage::Surface(rect) => *rect,
|
||||||
};
|
};
|
||||||
rect.loc += location;
|
rect.loc += location;
|
||||||
|
|
|
@ -406,10 +406,11 @@ impl<N: Coordinate> Point<N, Logical> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Convert this logical point to buffer coordinate space according to given scale factor
|
/// 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 {
|
Point {
|
||||||
x: self.x.upscale(scale),
|
x: point.x.upscale(scale),
|
||||||
y: self.y.upscale(scale),
|
y: point.y.upscale(scale),
|
||||||
_kind: std::marker::PhantomData,
|
_kind: std::marker::PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -430,10 +431,11 @@ impl<N: Coordinate> Point<N, Physical> {
|
||||||
impl<N: Coordinate> Point<N, Buffer> {
|
impl<N: Coordinate> Point<N, Buffer> {
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Convert this physical point to logical coordinate space according to given scale factor
|
/// 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 {
|
Point {
|
||||||
x: self.x.downscale(scale),
|
x: point.x.downscale(scale),
|
||||||
y: self.y.downscale(scale),
|
y: point.y.downscale(scale),
|
||||||
_kind: std::marker::PhantomData,
|
_kind: std::marker::PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -667,12 +669,12 @@ impl<N: Coordinate> Size<N, Logical> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Convert this logical size to buffer coordinate space according to given scale factor
|
/// Convert this logical size to buffer coordinate space according to given scale factor
|
||||||
pub fn to_buffer(self, scale: N) -> Size<N, Buffer> {
|
pub fn to_buffer(self, scale: N, transformation: Transform) -> Size<N, Buffer> {
|
||||||
Size {
|
transformation.transform_size(Size {
|
||||||
w: self.w.upscale(scale),
|
w: self.w.upscale(scale),
|
||||||
h: self.h.upscale(scale),
|
h: self.h.upscale(scale),
|
||||||
_kind: std::marker::PhantomData,
|
_kind: std::marker::PhantomData,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -691,12 +693,12 @@ impl<N: Coordinate> Size<N, Physical> {
|
||||||
impl<N: Coordinate> Size<N, Buffer> {
|
impl<N: Coordinate> Size<N, Buffer> {
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Convert this physical point to logical coordinate space according to given scale factor
|
/// Convert this physical point to logical coordinate space according to given scale factor
|
||||||
pub fn to_logical(self, scale: N) -> Size<N, Logical> {
|
pub fn to_logical(self, scale: N, transformation: Transform) -> Size<N, Logical> {
|
||||||
Size {
|
transformation.invert().transform_size(Size {
|
||||||
w: self.w.downscale(scale),
|
w: self.w.downscale(scale),
|
||||||
h: self.h.downscale(scale),
|
h: self.h.downscale(scale),
|
||||||
_kind: std::marker::PhantomData,
|
_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
|
/// Convert this logical rectangle to buffer coordinate space according to given scale factor
|
||||||
#[inline]
|
#[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 {
|
Rectangle {
|
||||||
loc: self.loc.to_buffer(scale),
|
loc: Point {
|
||||||
size: self.size.to_buffer(scale),
|
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> {
|
impl<N: Coordinate> Rectangle<N, Buffer> {
|
||||||
/// Convert this physical rectangle to logical coordinate space according to given scale factor
|
/// Convert this physical rectangle to logical coordinate space according to given scale factor
|
||||||
#[inline]
|
#[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 {
|
Rectangle {
|
||||||
loc: self.loc.to_logical(scale),
|
loc: Point {
|
||||||
size: self.size.to_logical(scale),
|
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(crate) mod ids;
|
||||||
pub mod user_data;
|
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
|
/// This resource is not managed by Smithay
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
Loading…
Reference in New Issue