diff options
Diffstat (limited to 'src/layout')
| -rw-r--r-- | src/layout/mod.rs | 138 | ||||
| -rw-r--r-- | src/layout/monitor.rs | 25 | ||||
| -rw-r--r-- | src/layout/workspace.rs | 37 |
3 files changed, 200 insertions, 0 deletions
diff --git a/src/layout/mod.rs b/src/layout/mod.rs index acd26348..dff5c0d0 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -564,6 +564,58 @@ impl<W: LayoutElement> Layout<W> { } } + /// Adds a new window to the layout immediately to the right of another window. + /// + /// If that another window was active, activates the new window. + /// + /// Returns an output that the window was added to, if there were any outputs. + pub fn add_window_right_of( + &mut self, + right_of: &W, + window: W, + width: Option<ColumnWidth>, + is_full_width: bool, + ) -> Option<&Output> { + let width = width + .or(self.options.default_width) + .unwrap_or_else(|| ColumnWidth::Fixed(window.size().w)); + + match &mut self.monitor_set { + MonitorSet::Normal { + monitors, + active_monitor_idx, + .. + } => { + let mon_idx = monitors + .iter() + .position(|mon| mon.workspaces.iter().any(|ws| ws.has_window(right_of))) + .unwrap(); + let mon = &mut monitors[mon_idx]; + + let mut activate = false; + if mon_idx == *active_monitor_idx { + let active_ws = &mon.workspaces[mon.active_workspace_idx]; + if !active_ws.columns.is_empty() { + let active_col = &active_ws.columns[active_ws.active_column_idx]; + let active_tile = &active_col.tiles[active_col.active_tile_idx]; + activate = active_tile.window() == right_of; + } + } + + mon.add_window_right_of(right_of, window, activate, width, is_full_width); + Some(&mon.output) + } + MonitorSet::NoOutputs { workspaces } => { + let ws = workspaces + .iter_mut() + .find(|ws| ws.has_window(right_of)) + .unwrap(); + ws.add_window_right_of(right_of, window, true, width, is_full_width); + None + } + } + } + pub fn remove_window(&mut self, window: &W) { match &mut self.monitor_set { MonitorSet::Normal { monitors, .. } => { @@ -1777,6 +1829,16 @@ mod tests { #[proptest(strategy = "arbitrary_min_max_size()")] min_max_size: (Size<i32, Logical>, Size<i32, Logical>), }, + AddWindowRightOf { + #[proptest(strategy = "1..=5usize")] + id: usize, + #[proptest(strategy = "1..=5usize")] + right_of_id: usize, + #[proptest(strategy = "arbitrary_bbox()")] + bbox: Rectangle<i32, Logical>, + #[proptest(strategy = "arbitrary_min_max_size()")] + min_max_size: (Size<i32, Logical>, Size<i32, Logical>), + }, CloseWindow(#[proptest(strategy = "1..=5usize")] usize), FullscreenWindow(#[proptest(strategy = "1..=5usize")] usize), FocusColumnLeft, @@ -1897,6 +1959,58 @@ mod tests { let win = TestWindow::new(id, bbox, min_max_size.0, min_max_size.1); layout.add_window(win, None, false); } + Op::AddWindowRightOf { + id, + right_of_id, + bbox, + min_max_size, + } => { + let mut found_right_of = false; + + match &mut layout.monitor_set { + MonitorSet::Normal { monitors, .. } => { + for mon in monitors { + for ws in &mut mon.workspaces { + for win in ws.windows() { + if win.0.id == id { + return; + } + + if win.0.id == right_of_id { + found_right_of = true; + } + } + } + } + } + MonitorSet::NoOutputs { workspaces, .. } => { + for ws in workspaces { + for win in ws.windows() { + if win.0.id == id { + return; + } + + if win.0.id == right_of_id { + found_right_of = true; + } + } + } + } + } + + if !found_right_of { + return; + } + + let right_of_win = TestWindow::new( + right_of_id, + Rectangle::default(), + Size::default(), + Size::default(), + ); + let win = TestWindow::new(id, bbox, min_max_size.0, min_max_size.1); + layout.add_window_right_of(&right_of_win, win, None, false); + } Op::CloseWindow(id) => { let dummy = TestWindow::new(id, Rectangle::default(), Size::default(), Size::default()); @@ -2052,6 +2166,18 @@ mod tests { bbox: Rectangle::from_loc_and_size((0, 0), (100, 200)), min_max_size: Default::default(), }, + Op::AddWindowRightOf { + id: 3, + right_of_id: 0, + bbox: Rectangle::from_loc_and_size((0, 0), (100, 200)), + min_max_size: Default::default(), + }, + Op::AddWindowRightOf { + id: 4, + right_of_id: 1, + bbox: Rectangle::from_loc_and_size((0, 0), (100, 200)), + min_max_size: Default::default(), + }, Op::CloseWindow(0), Op::CloseWindow(1), Op::CloseWindow(2), @@ -2185,6 +2311,18 @@ mod tests { bbox: Rectangle::from_loc_and_size((0, 0), (100, 200)), min_max_size: Default::default(), }, + Op::AddWindowRightOf { + id: 6, + right_of_id: 0, + bbox: Rectangle::from_loc_and_size((0, 0), (100, 200)), + min_max_size: Default::default(), + }, + Op::AddWindowRightOf { + id: 7, + right_of_id: 1, + bbox: Rectangle::from_loc_and_size((0, 0), (100, 200)), + min_max_size: Default::default(), + }, Op::CloseWindow(0), Op::CloseWindow(1), Op::CloseWindow(2), diff --git a/src/layout/monitor.rs b/src/layout/monitor.rs index 0e5802cd..f5da804a 100644 --- a/src/layout/monitor.rs +++ b/src/layout/monitor.rs @@ -126,6 +126,31 @@ impl<W: LayoutElement> Monitor<W> { } } + pub fn add_window_right_of( + &mut self, + right_of: &W, + window: W, + activate: bool, + width: ColumnWidth, + is_full_width: bool, + ) { + let workspace_idx = self + .workspaces + .iter_mut() + .position(|ws| ws.has_window(right_of)) + .unwrap(); + let workspace = &mut self.workspaces[workspace_idx]; + + workspace.add_window_right_of(right_of, window, activate, width, is_full_width); + + // After adding a new window, workspace becomes this output's own. + workspace.original_output = OutputId::new(&self.output); + + if activate { + self.activate_workspace(workspace_idx); + } + } + pub fn add_column(&mut self, workspace_idx: usize, column: Column<W>, activate: bool) { let workspace = &mut self.workspaces[workspace_idx]; diff --git a/src/layout/workspace.rs b/src/layout/workspace.rs index 6e2a7c00..47be5877 100644 --- a/src/layout/workspace.rs +++ b/src/layout/workspace.rs @@ -555,6 +555,43 @@ impl<W: LayoutElement> Workspace<W> { } } + pub fn add_window_right_of( + &mut self, + right_of: &W, + window: W, + activate: bool, + width: ColumnWidth, + is_full_width: bool, + ) { + self.enter_output_for_window(&window); + + let idx = self + .columns + .iter() + .position(|col| col.contains(right_of)) + .unwrap() + + 1; + + let column = Column::new( + window, + self.view_size, + self.working_area, + self.options.clone(), + width, + is_full_width, + ); + self.columns.insert(idx, column); + + if self.active_column_idx >= idx { + self.active_column_idx += 1; + } + + if activate { + self.activate_column(idx); + self.activate_prev_column_on_removal = true; + } + } + pub fn add_column(&mut self, mut column: Column<W>, activate: bool) { for tile in &column.tiles { self.enter_output_for_window(tile.window()); |
