From be7fbd418fcee2d2ff9f80aa15f1eb8ff0d83afb Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Mon, 14 Oct 2024 18:08:44 +0300 Subject: layout: Return Tile + info upon removal --- src/layout/mod.rs | 36 ++++++++++++++--------- src/layout/monitor.rs | 62 +++++++++++++++++++++------------------ src/layout/workspace.rs | 77 +++++++++++++++++++++++-------------------------- 3 files changed, 93 insertions(+), 82 deletions(-) (limited to 'src/layout') diff --git a/src/layout/mod.rs b/src/layout/mod.rs index e889fe2c..0f6c0bef 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -44,6 +44,7 @@ use smithay::backend::renderer::gles::{GlesRenderer, GlesTexture}; use smithay::output::{self, Output}; use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface; use smithay::utils::{Logical, Point, Scale, Serial, Size, Transform}; +use tile::Tile; use workspace::WorkspaceId; pub use self::monitor::MonitorRenderElement; @@ -281,6 +282,15 @@ impl Default for Options { } } +/// Tile that was just removed from the layout. +pub struct RemovedTile { + tile: Tile, + /// Width of the column the tile was in. + width: ColumnWidth, + /// Whether the column the tile was in was full-width. + is_full_width: bool, +} + impl Options { fn from_config(config: &Config) -> Self { let layout = &config.layout; @@ -743,13 +753,17 @@ impl Layout { ); } - pub fn remove_window(&mut self, window: &W::Id, transaction: Transaction) -> Option { + pub fn remove_window( + &mut self, + window: &W::Id, + transaction: Transaction, + ) -> Option> { match &mut self.monitor_set { MonitorSet::Normal { monitors, .. } => { for mon in monitors { for (idx, ws) in mon.workspaces.iter_mut().enumerate() { if ws.has_window(window) { - let win = ws.remove_window(window, transaction); + let removed = ws.remove_tile(window, transaction); // Clean up empty workspaces that are not active and not last. if !ws.has_windows() @@ -765,7 +779,7 @@ impl Layout { } } - return Some(win); + return Some(removed); } } } @@ -773,14 +787,14 @@ impl Layout { MonitorSet::NoOutputs { workspaces, .. } => { for (idx, ws) in workspaces.iter_mut().enumerate() { if ws.has_window(window) { - let win = ws.remove_window(window, transaction); + let removed = ws.remove_tile(window, transaction); // Clean up empty workspaces. if !ws.has_windows() && ws.name.is_none() { workspaces.remove(idx); } - return Some(win); + return Some(removed); } } } @@ -2111,24 +2125,20 @@ impl Layout { let mon = &mut monitors[mon_idx]; let ws = &mut mon.workspaces[ws_idx]; let column = &ws.columns[col_idx]; - let width = column.width; - let is_full_width = column.is_full_width; let activate = mon_idx == *active_monitor_idx && ws_idx == mon.active_workspace_idx && col_idx == ws.active_column_idx && tile_idx == column.active_tile_idx; - let window = ws - .remove_tile_by_idx(col_idx, tile_idx, Transaction::new(), None) - .into_window(); + let removed = ws.remove_tile_by_idx(col_idx, tile_idx, Transaction::new(), None); self.add_window_by_idx( new_idx, workspace_idx, - window, + removed.tile.into_window(), activate, - width, - is_full_width, + removed.width, + removed.is_full_width, ); let MonitorSet::Normal { monitors, .. } = &mut self.monitor_set else { diff --git a/src/layout/monitor.rs b/src/layout/monitor.rs index 71204ce7..9d665bee 100644 --- a/src/layout/monitor.rs +++ b/src/layout/monitor.rs @@ -458,18 +458,20 @@ impl Monitor { } let column = &workspace.columns[workspace.active_column_idx]; - let width = column.width; - let is_full_width = column.is_full_width; - let window = workspace - .remove_tile_by_idx( - workspace.active_column_idx, - column.active_tile_idx, - Transaction::new(), - None, - ) - .into_window(); + let removed = workspace.remove_tile_by_idx( + workspace.active_column_idx, + column.active_tile_idx, + Transaction::new(), + None, + ); - self.add_window(new_idx, window, true, width, is_full_width); + self.add_window( + new_idx, + removed.tile.into_window(), + true, + removed.width, + removed.is_full_width, + ); } pub fn move_to_workspace_down(&mut self) { @@ -486,18 +488,20 @@ impl Monitor { } let column = &workspace.columns[workspace.active_column_idx]; - let width = column.width; - let is_full_width = column.is_full_width; - let window = workspace - .remove_tile_by_idx( - workspace.active_column_idx, - column.active_tile_idx, - Transaction::new(), - None, - ) - .into_window(); + let removed = workspace.remove_tile_by_idx( + workspace.active_column_idx, + column.active_tile_idx, + Transaction::new(), + None, + ); - self.add_window(new_idx, window, true, width, is_full_width); + self.add_window( + new_idx, + removed.tile.into_window(), + true, + removed.width, + removed.is_full_width, + ); } pub fn move_to_workspace(&mut self, window: Option<&W::Id>, idx: usize) { @@ -534,17 +538,19 @@ impl Monitor { let workspace = &mut self.workspaces[source_workspace_idx]; let column = &workspace.columns[col_idx]; - let width = column.width; - let is_full_width = column.is_full_width; let activate = source_workspace_idx == self.active_workspace_idx && col_idx == workspace.active_column_idx && tile_idx == column.active_tile_idx; - let window = workspace - .remove_tile_by_idx(col_idx, tile_idx, Transaction::new(), None) - .into_window(); + let removed = workspace.remove_tile_by_idx(col_idx, tile_idx, Transaction::new(), None); - self.add_window(new_idx, window, activate, width, is_full_width); + self.add_window( + new_idx, + removed.tile.into_window(), + activate, + removed.width, + removed.is_full_width, + ); if self.workspace_switch.is_none() { self.clean_up_workspaces(); diff --git a/src/layout/workspace.rs b/src/layout/workspace.rs index 0348dfa7..b1afa24d 100644 --- a/src/layout/workspace.rs +++ b/src/layout/workspace.rs @@ -17,7 +17,7 @@ use smithay::utils::{Logical, Point, Rectangle, Scale, Serial, Size, Transform}; use super::closing_window::{ClosingWindow, ClosingWindowRenderElement}; use super::tile::{Tile, TileRenderElement}; -use super::{ConfigureIntent, InteractiveResizeData, LayoutElement, Options}; +use super::{ConfigureIntent, InteractiveResizeData, LayoutElement, Options, RemovedTile}; use crate::animation::Animation; use crate::input::swipe_tracker::SwipeTracker; use crate::niri_render_elements; @@ -1124,10 +1124,10 @@ impl Workspace { pub fn remove_tile_by_idx( &mut self, column_idx: usize, - window_idx: usize, + tile_idx: usize, transaction: Transaction, anim_config: Option, - ) -> Tile { + ) -> RemovedTile { let offset = self.column_x(column_idx + 1) - self.column_x(column_idx); let column = &mut self.columns[column_idx]; @@ -1136,13 +1136,13 @@ impl Workspace { // Animate movement of other tiles. // FIXME: tiles can move by X too, in a centered or resizing layout with one window smaller // than the others. - let offset_y = column.tile_offset(window_idx + 1).y - column.tile_offset(window_idx).y; - for tile in &mut column.tiles[window_idx + 1..] { + let offset_y = column.tile_offset(tile_idx + 1).y - column.tile_offset(tile_idx).y; + for tile in &mut column.tiles[tile_idx + 1..] { tile.animate_move_y_from(offset_y); } - let tile = column.tiles.remove(window_idx); - column.data.remove(window_idx); + let tile = column.tiles.remove(tile_idx); + column.data.remove(tile_idx); // If one window is left, reset its weight to 1. if column.data.len() == 1 { @@ -1162,6 +1162,12 @@ impl Workspace { } } + let tile = RemovedTile { + tile, + width: column.width, + is_full_width: column.is_full_width, + }; + let became_empty = column.tiles.is_empty(); let offset = if became_empty { offset @@ -1322,7 +1328,7 @@ impl Workspace { column } - pub fn remove_window(&mut self, window: &W::Id, transaction: Transaction) -> W { + pub fn remove_tile(&mut self, window: &W::Id, transaction: Transaction) -> RemovedTile { let column_idx = self .columns .iter() @@ -1330,9 +1336,8 @@ impl Workspace { .unwrap(); let column = &self.columns[column_idx]; - let window_idx = column.position(window).unwrap(); - self.remove_tile_by_idx(column_idx, window_idx, transaction, None) - .into_window() + let tile_idx = column.position(window).unwrap(); + self.remove_tile_by_idx(column_idx, tile_idx, transaction, None) } pub fn update_window(&mut self, window: &W::Id, serial: Option) { @@ -1852,7 +1857,7 @@ impl Workspace { } offset.x += self.columns[source_col_idx].render_offset().x; - let tile = self.remove_tile_by_idx( + let RemovedTile { tile, .. } = self.remove_tile_by_idx( source_col_idx, 0, Transaction::new(), @@ -1868,12 +1873,9 @@ impl Workspace { new_tile.animate_move_from(offset); } else { // Move out of column. - let width = source_column.width; - let is_full_width = source_column.is_full_width; - let mut offset = Point::from((source_column.render_offset().x, 0.)); - let tile = + let removed = self.remove_tile_by_idx(source_col_idx, source_tile_idx, Transaction::new(), None); // We're inserting into the source column position. @@ -1881,10 +1883,10 @@ impl Workspace { self.add_tile( Some(target_column_idx), - tile, + removed.tile, source_tile_was_active, - width, - is_full_width, + removed.width, + removed.is_full_width, Some(self.options.animations.window_movement.0), ); @@ -1951,7 +1953,7 @@ impl Workspace { self.activate_prev_column_on_removal = None; } - let tile = self.remove_tile_by_idx( + let RemovedTile { tile, .. } = self.remove_tile_by_idx( source_col_idx, 0, Transaction::new(), @@ -1966,22 +1968,19 @@ impl Workspace { new_tile.animate_move_from(offset); } else { // Move out of column. - let width = source_column.width; - let is_full_width = source_column.is_full_width; - let prev_width = self.data[source_col_idx].width; - let tile = + let removed = self.remove_tile_by_idx(source_col_idx, source_tile_idx, Transaction::new(), None); let target_column_idx = source_col_idx + 1; self.add_tile( Some(target_column_idx), - tile, + removed.tile, source_tile_was_active, - width, - is_full_width, + removed.width, + removed.is_full_width, Some(self.options.animations.window_movement.0), ); @@ -2017,8 +2016,8 @@ impl Workspace { let mut offset = Point::from((offset, 0.)); let prev_off = self.columns[source_column_idx].tile_offset(0); - let tile = self.remove_tile_by_idx(source_column_idx, 0, Transaction::new(), None); - self.add_tile_to_column(target_column_idx, None, tile, false); + let removed = self.remove_tile_by_idx(source_column_idx, 0, Transaction::new(), None); + self.add_tile_to_column(target_column_idx, None, removed.tile, false); let target_column = &mut self.columns[target_column_idx]; offset += prev_off - target_column.tile_offset(target_column.tiles.len() - 1); @@ -2045,9 +2044,7 @@ impl Workspace { let mut offset = Point::from((source_column.render_offset().x, 0.)); let prev_off = source_column.tile_offset(source_column.active_tile_idx); - let width = source_column.width; - let is_full_width = source_column.is_full_width; - let tile = self.remove_tile_by_idx( + let removed = self.remove_tile_by_idx( source_col_idx, source_column.active_tile_idx, Transaction::new(), @@ -2056,10 +2053,10 @@ impl Workspace { self.add_tile( Some(target_col_idx), - tile, + removed.tile, true, - width, - is_full_width, + removed.width, + removed.is_full_width, Some(self.options.animations.window_movement.0), ); @@ -2412,19 +2409,17 @@ impl Workspace { if is_fullscreen && col.tiles.len() > 1 { // This wasn't the only window in its column; extract it into a separate column. let activate = self.active_column_idx == col_idx && col.active_tile_idx == tile_idx; - let width = col.width; - let is_full_width = col.is_full_width; - let tile = self.remove_tile_by_idx(col_idx, tile_idx, Transaction::new(), None); + let removed = self.remove_tile_by_idx(col_idx, tile_idx, Transaction::new(), None); // Create a column manually to disable the resize animation. let column = Column::new_with_tile( - tile, + removed.tile, self.view_size, self.working_area, self.scale.fractional_scale(), self.options.clone(), - width, - is_full_width, + removed.width, + removed.is_full_width, false, ); self.add_column(Some(col_idx + 1), column, activate, None); -- cgit