use std::rc::Rc;
use niri_config::{Color, CornerRadius, GradientInterpolation};
use smithay::backend::allocator::Fourcc;
use smithay::backend::renderer::element::{Element, Kind};
use smithay::backend::renderer::gles::GlesRenderer;
use smithay::utils::{Logical, Point, Rectangle, Scale, Size, Transform};
use super::focus_ring::{FocusRing, FocusRingRenderElement};
use super::opening_window::{OpenAnimation, OpeningWindowRenderElement};
use super::{
LayoutElement, LayoutElementRenderElement, LayoutElementRenderSnapshot, Options, SizeFrac,
RESIZE_ANIMATION_THRESHOLD,
};
use crate::animation::{Animation, Clock};
use crate::niri_render_elements;
use crate::render_helpers::border::BorderRenderElement;
use crate::render_helpers::clipped_surface::{ClippedSurfaceRenderElement, RoundedCornerDamage};
use crate::render_helpers::damage::ExtraDamage;
use crate::render_helpers::renderer::NiriRenderer;
use crate::render_helpers::resize::ResizeRenderElement;
use crate::render_helpers::snapshot::RenderSnapshot;
use crate::render_helpers::solid_color::{SolidColorBuffer, SolidColorRenderElement};
use crate::render_helpers::{render_to_encompassing_texture, RenderTarget};
use crate::utils::transaction::Transaction;
/// Toplevel window with decorations.
#[derive(Debug)]
pub struct Tile<W: LayoutElement> {
/// The toplevel window itself.
window: W,
/// The border around the window.
border: FocusRing,
/// The focus ring around the window.
///
/// It's supposed to be on the Workspace, but for the sake of a nicer open animation it's
/// currently here.
focus_ring: FocusRing,
/// Whether this tile is fullscreen.
///
/// This will update only when the `window` actually goes fullscreen, rather than right away,
/// to avoid black backdrop flicker before the window has had a chance to resize.
is_fullscreen: bool,
/// The black backdrop for fullscreen windows.
fullscreen_backdrop: SolidColorBuffer,
/// Whether the tile should float upon unfullscreening.
pub(super) unfullscreen_to_floating: bool,
/// The size that the window should assume when going floating.
///
/// This is generally the last size the window had when it was floating. It can be unknown if
/// the window starts out in the tiling layout or fullscreen.
pub(super) floating_window_size: Option<Size<i32, Logical>>,
/// The position that the tile should assume when going floating, relative to the floating
/// space working area.
///
/// This is generally the last position the tile had when it was floating. It can be unknown if
/// the window starts out in the tiling layout.
pub(super) floating_pos: Option<Point<f64, SizeFrac>>,
/// Currently selected preset width index when this tile is floating.
pub(super) floating_preset_width_idx: Option<usize>,
/// Currently selected preset height index when this tile is floating.
pub(super) floating_preset_height_idx: Option<usize>,
/// The animation upon opening a window.
open_animation: Option<OpenAnimation>,
/// The animation of the window resizing.
resize_animation: Option<ResizeAnimation>,
/// The animation of a tile visually moving horizontally.
move_x_animation: Option<MoveAnimation>,
/// The animation of a tile visually moving vertically.
move_y_animation: Option<MoveAnimation>,
/// Offset during the initial interactive move rubberband.
pub(super) interactive_move_offset: Point<f64, Logical>,
/// Snapshot of the last render for use in the close animation.
unmap_snapshot: Option<TileRenderSnapshot>,
/// Extra damage for clipped surface corner radius changes.
rounded_corner_damage: RoundedCornerDamage,
/// The view size for the tile's workspace.
///
/// Used as the fullscreen target size.
view_size: Size<f64, Logical>,
/// Scale of the output the tile is on (and rounds its sizes to).
scale: f64,
/// Clock for driving animations.
pub(super) clock: Clock,
/// Configurable properties of the layout.
pub(super) options: Rc<Options>,
}
niri_render_elements! {
TileRenderElement<R> => {
LayoutElement = LayoutElementRenderElement<R>,
FocusRing = FocusRingRenderElement,
SolidColor = SolidColorRenderElement,
Opening = OpeningWindowRenderElement,
Resize = ResizeRenderElement,
Border = BorderRenderElement,
ClippedSurface = ClippedSurfaceRenderElement<R>,
ExtraDamage = ExtraDamage,
}
}
pub type TileRenderSnapshot =
RenderSnapshot<TileRenderElement<GlesRenderer>, TileRenderElement<GlesRenderer>>;
#[derive(Debug)]
struct ResizeAnimation {
anim: Animation,
size_from: Size<f64, Logical>,
snapshot: LayoutElementRenderSnapshot,
}
#[derive(Debug)]
struct MoveAnimation {
anim: Animation,
from: f64,
}
impl<W: LayoutElement> Tile<W> {
pub fn new(
window: W,
view_size: Size<f64, Logical>,
scale: f64,
clock: Clock,
options: Rc<Options>,