aboutsummaryrefslogtreecommitdiff
path: root/src/layout/monitor.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/layout/monitor.rs')
-rw-r--r--src/layout/monitor.rs204
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();