diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2024-12-26 09:37:38 +0300 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2024-12-30 20:12:37 +0300 |
| commit | daaee43be387d75c62c7ba63d33b0b8f9ae192c8 (patch) | |
| tree | d44840951d79e255bcc95300933081b8bb0bd40e /src/layout/monitor.rs | |
| parent | 0d71cb93aff0c639837cec51938a2450f8945bd7 (diff) | |
| download | niri-daaee43be387d75c62c7ba63d33b0b8f9ae192c8.tar.gz niri-daaee43be387d75c62c7ba63d33b0b8f9ae192c8.tar.bz2 niri-daaee43be387d75c62c7ba63d33b0b8f9ae192c8.zip | |
layout: Refactor window opening targets
Diffstat (limited to 'src/layout/monitor.rs')
| -rw-r--r-- | src/layout/monitor.rs | 204 |
1 files changed, 95 insertions, 109 deletions
diff --git a/src/layout/monitor.rs b/src/layout/monitor.rs index 3ef1b605..d61d8a45 100644 --- a/src/layout/monitor.rs +++ b/src/layout/monitor.rs @@ -11,8 +11,10 @@ use smithay::utils::{Logical, Point, Rectangle}; use super::scrolling::{Column, ColumnWidth}; use super::tile::Tile; -use super::workspace::{OutputId, Workspace, WorkspaceId, WorkspaceRenderElement}; -use super::{LayoutElement, Options}; +use super::workspace::{ + OutputId, Workspace, WorkspaceAddWindowTarget, WorkspaceId, WorkspaceRenderElement, +}; +use super::{ActivateWindow, LayoutElement, Options}; use crate::animation::{Animation, Clock}; use crate::input::swipe_tracker::SwipeTracker; use crate::render_helpers::renderer::NiriRenderer; @@ -66,6 +68,23 @@ pub struct WorkspaceSwitchGesture { 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>>>; @@ -220,56 +239,18 @@ impl<W: LayoutElement> Monitor<W> { pub fn add_window( &mut self, - mut workspace_idx: usize, - window: W, - activate: bool, - width: ColumnWidth, - is_full_width: bool, - is_floating: bool, - ) { - let workspace = &mut self.workspaces[workspace_idx]; - - workspace.add_window(window, activate, width, is_full_width, is_floating); - - // After adding a new window, workspace becomes this output's own. - workspace.original_output = OutputId::new(&self.output); - - if workspace_idx == self.workspaces.len() - 1 { - self.add_workspace_bottom(); - } - - if self.options.empty_workspace_above_first && workspace_idx == 0 { - self.add_workspace_top(); - workspace_idx += 1; - } - - if activate { - self.activate_workspace(workspace_idx); - } - } - - pub fn add_window_right_of( - &mut self, - right_of: &W::Id, window: W, + target: MonitorAddWindowTarget<W>, + activate: ActivateWindow, width: ColumnWidth, is_full_width: bool, is_floating: bool, ) { - let workspace_idx = self - .workspaces - .iter_mut() - .position(|ws| ws.has_window(right_of)) - .unwrap(); - let workspace = &mut self.workspaces[workspace_idx]; + // Currently, everything a workspace sets on a Tile is the same across all workspaces of a + // monitor. So we can use any workspace, not necessarily the exact target workspace. + let tile = self.workspaces[0].make_tile(window); - workspace.add_window_right_of(right_of, window, width, is_full_width, is_floating); - - // After adding a new window, workspace becomes this output's own. - workspace.original_output = OutputId::new(&self.output); - - // Since we're adding window right of something, the workspace isn't empty, and therefore - // cannot be the last one, so we never need to insert a new empty workspace. + self.add_tile(tile, target, activate, width, is_full_width, is_floating); } pub fn add_column(&mut self, mut workspace_idx: usize, column: Column<W>, activate: bool) { @@ -295,39 +276,39 @@ impl<W: LayoutElement> Monitor<W> { pub fn add_tile( &mut self, - mut workspace_idx: usize, - column_idx: Option<usize>, tile: Tile<W>, - activate: bool, + target: MonitorAddWindowTarget<W>, + activate: ActivateWindow, width: ColumnWidth, is_full_width: bool, + is_floating: bool, ) { - let workspace = &mut self.workspaces[workspace_idx]; - - workspace.add_tile(column_idx, tile, activate, width, is_full_width); - - // After adding a new window, workspace becomes this output's own. - workspace.original_output = OutputId::new(&self.output); - - if workspace_idx == self.workspaces.len() - 1 { - // Insert a new empty workspace. - self.add_workspace_bottom(); - } - - if self.options.empty_workspace_above_first && workspace_idx == 0 { - self.add_workspace_top(); - workspace_idx += 1; - } - - if activate { - self.activate_workspace(workspace_idx); - } - } + let (mut workspace_idx, target) = match target { + MonitorAddWindowTarget::Auto => { + (self.active_workspace_idx, WorkspaceAddWindowTarget::Auto) + } + MonitorAddWindowTarget::Workspace { id, column_idx } => { + let idx = self.workspaces.iter().position(|ws| ws.id() == id).unwrap(); + let target = if let Some(column_idx) = column_idx { + WorkspaceAddWindowTarget::NewColumnAt(column_idx) + } else { + WorkspaceAddWindowTarget::Auto + }; + (idx, target) + } + MonitorAddWindowTarget::NextTo(win_id) => { + let idx = self + .workspaces + .iter_mut() + .position(|ws| ws.has_window(win_id)) + .unwrap(); + (idx, WorkspaceAddWindowTarget::NextTo(win_id)) + } + }; - pub fn add_floating_tile(&mut self, mut workspace_idx: usize, tile: Tile<W>, activate: bool) { let workspace = &mut self.workspaces[workspace_idx]; - workspace.add_floating_tile(tile, activate); + workspace.add_tile(tile, target, activate, width, is_full_width, is_floating); // After adding a new window, workspace becomes this output's own. workspace.original_output = OutputId::new(&self.output); @@ -342,7 +323,7 @@ impl<W: LayoutElement> Monitor<W> { workspace_idx += 1; } - if activate { + if activate.map_smart(|| false) { self.activate_workspace(workspace_idx); } } @@ -518,24 +499,24 @@ impl<W: LayoutElement> Monitor<W> { if new_idx == source_workspace_idx { return; } + let new_id = self.workspaces[new_idx].id(); let workspace = &mut self.workspaces[source_workspace_idx]; let Some(removed) = workspace.remove_active_tile(Transaction::new()) else { return; }; - if removed.is_floating { - self.add_floating_tile(new_idx, removed.tile, true); - } else { - self.add_tile( - new_idx, - None, - removed.tile, - true, - removed.width, - removed.is_full_width, - ); - } + self.add_tile( + removed.tile, + MonitorAddWindowTarget::Workspace { + id: new_id, + column_idx: None, + }, + ActivateWindow::Yes, + removed.width, + removed.is_full_width, + removed.is_floating, + ); } pub fn move_to_workspace_down(&mut self) { @@ -545,24 +526,24 @@ impl<W: LayoutElement> Monitor<W> { if new_idx == source_workspace_idx { return; } + let new_id = self.workspaces[new_idx].id(); let workspace = &mut self.workspaces[source_workspace_idx]; let Some(removed) = workspace.remove_active_tile(Transaction::new()) else { return; }; - if removed.is_floating { - self.add_floating_tile(new_idx, removed.tile, true); - } else { - self.add_tile( - new_idx, - None, - removed.tile, - true, - removed.width, - removed.is_full_width, - ); - } + self.add_tile( + removed.tile, + MonitorAddWindowTarget::Workspace { + id: new_id, + column_idx: None, + }, + ActivateWindow::Yes, + removed.width, + removed.is_full_width, + removed.is_floating, + ); } pub fn move_to_workspace(&mut self, window: Option<&W::Id>, idx: usize) { @@ -579,10 +560,16 @@ impl<W: LayoutElement> Monitor<W> { if new_idx == source_workspace_idx { return; } + let new_id = self.workspaces[new_idx].id(); let activate = window.map_or(true, |win| { self.active_window().map(|win| win.id()) == Some(win) }); + let activate = if activate { + ActivateWindow::Yes + } else { + ActivateWindow::No + }; let workspace = &mut self.workspaces[source_workspace_idx]; let transaction = Transaction::new(); @@ -594,18 +581,17 @@ impl<W: LayoutElement> Monitor<W> { return; }; - if removed.is_floating { - self.add_floating_tile(new_idx, removed.tile, activate); - } else { - self.add_tile( - new_idx, - None, - removed.tile, - activate, - removed.width, - removed.is_full_width, - ); - } + self.add_tile( + removed.tile, + MonitorAddWindowTarget::Workspace { + id: new_id, + column_idx: None, + }, + activate, + removed.width, + removed.is_full_width, + removed.is_floating, + ); if self.workspace_switch.is_none() { self.clean_up_workspaces(); |
