use std::cmp::min;
use std::rc::Rc;
use std::time::Duration;
use niri_ipc::{ColumnDisplay, SizeChange};
use smithay::backend::renderer::element::utils::{
CropRenderElement, Relocate, RelocateRenderElement,
};
use smithay::output::Output;
use smithay::utils::{Logical, Point, Rectangle, Size};
use super::scrolling::{Column, ColumnWidth, ScrollDirection};
use super::tile::Tile;
use super::workspace::{
OutputId, Workspace, WorkspaceAddWindowTarget, WorkspaceId, WorkspaceRenderElement,
};
use super::{ActivateWindow, HitType, LayoutElement, Options};
use crate::animation::{Animation, Clock};
use crate::input::swipe_tracker::SwipeTracker;
use crate::render_helpers::renderer::NiriRenderer;
use crate::render_helpers::RenderTarget;
use crate::rubber_band::RubberBand;
use crate::utils::transaction::Transaction;
use crate::utils::{output_size, round_logical_in_physical, ResizeEdge};
/// Amount of touchpad movement to scroll the height of one workspace.
const WORKSPACE_GESTURE_MOVEMENT: f64 = 300.;
const WORKSPACE_GESTURE_RUBBER_BAND: RubberBand = RubberBand {
stiffness: 0.5,
limit: 0.05,
};
#[derive(Debug)]
pub struct Monitor<W: LayoutElement> {
/// Output for this monitor.
pub(super) output: Output,
/// Cached name of the output.
output_name: String,
// Must always contain at least one.
pub(super) workspaces: Vec<Workspace<W>>,
/// Index of the currently active workspace.
pub(super) active_workspace_idx: usize,
/// ID of the previously active workspace.
pub(super) previous_workspace_id: Option<WorkspaceId>,
/// In-progress switch between workspaces.
pub(super) workspace_switch: Option<WorkspaceSwitch>,
/// Clock for driving animations.
pub(super) clock: Clock,
/// Configurable properties of the layout.
pub(super) options: Rc<Options>,
}
#[derive(Debug)]
pub enum WorkspaceSwitch {
Animation(Animation),
Gesture(WorkspaceSwitchGesture),
}
#[derive(Debug)]
pub struct WorkspaceSwitchGesture {
/// Index of the workspace where the gesture was started.
center_idx: usize,
/// Current, fractional workspace index.
pub(super) current_idx: f64,
tracker: SwipeTracker,
/// Whether the gesture is controlled by the touchpad.
is_touchpad: bool,
}
/// Where to put a newly added window.
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub enum MonitorAddWindowTarget<'a, W: LayoutElement> {
/// No particular preference.
#[default]
Auto,
/// On this workspace.
Workspace {
/// Id of the target workspace.
id: WorkspaceId,
/// Override where the window will open as a new column.
column_idx: Option<usize>,
},
/// Next to this existing window.
NextTo(&'a W::Id),
}
pub type MonitorRenderElement<R> =
RelocateRenderElement<CropRenderElement<WorkspaceRenderElement<R>>>;
impl WorkspaceSwitch {
pub fn current_idx(&self) -> f64 {
match self {