aboutsummaryrefslogtreecommitdiff
path: root/src/layout/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/layout/mod.rs')
-rw-r--r--src/layout/mod.rs82
1 files changed, 63 insertions, 19 deletions
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index b5b137ea..e6dacfde 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -380,6 +380,12 @@ struct InteractiveMoveData<W: LayoutElement> {
///
/// This helps the pointer remain inside the window as it resizes.
pub(self) pointer_ratio_within_window: (f64, f64),
+ /// Config overrides for the workspace where the window is currently located.
+ ///
+ /// To avoid sudden window changes when starting an interactive move, it will remember the
+ /// config overrides for the workspace where the move originated from. As soon as the window
+ /// moves over some different workspace though, this override will reset.
+ pub(self) workspace_config: Option<(WorkspaceId, niri_config::LayoutPart)>,
}
#[derive(Debug)]
@@ -576,6 +582,13 @@ impl Options {
}
}
+ fn with_merged_layout(mut self, part: Option<&niri_config::LayoutPart>) -> Self {
+ if let Some(part) = part {
+ self.layout.merge_with(part);
+ }
+ self
+ }
+
fn adjusted_for_scale(mut self, scale: f64) -> Self {
let round = |logical: f64| round_logical_in_physical_max1(scale, logical);
@@ -2296,7 +2309,9 @@ impl<W: LayoutElement> Layout<W> {
move_.tile.verify_invariants();
let scale = move_.output.current_scale().fractional_scale();
- let options = Options::clone(&self.options).adjusted_for_scale(scale);
+ let options = Options::clone(&self.options)
+ .with_merged_layout(move_.workspace_config.as_ref().map(|(_, c)| c))
+ .adjusted_for_scale(scale);
assert_eq!(
&*move_.tile.options, &options,
"interactive moved tile options must be \
@@ -2830,6 +2845,14 @@ impl<W: LayoutElement> Layout<W> {
}
pub fn update_config(&mut self, config: &Config) {
+ // Update workspace-specific config for all named workspaces.
+ for ws in self.workspaces_mut() {
+ let Some(name) = ws.name() else { continue };
+ if let Some(config) = config.workspaces.iter().find(|w| &w.name.0 == name) {
+ ws.update_layout_config(config.layout.clone().map(|x| x.0));
+ }
+ }
+
self.update_options(Options::from_config(config));
}
@@ -2839,11 +2862,10 @@ impl<W: LayoutElement> Layout<W> {
if let Some(InteractiveMoveState::Moving(move_)) = &mut self.interactive_move {
let view_size = output_size(&move_.output);
let scale = move_.output.current_scale().fractional_scale();
- move_.tile.update_config(
- view_size,
- scale,
- Rc::new(Options::clone(&options).adjusted_for_scale(scale)),
- );
+ let options = Options::clone(&options)
+ .with_merged_layout(move_.workspace_config.as_ref().map(|(_, c)| c))
+ .adjusted_for_scale(scale);
+ move_.tile.update_config(view_size, scale, Rc::new(options));
}
match &mut self.monitor_set {
@@ -3737,15 +3759,17 @@ impl<W: LayoutElement> Layout<W> {
}
.band(sq_dist / INTERACTIVE_MOVE_START_THRESHOLD);
- let (is_floating, tile) = self
+ let (is_floating, tile, workspace_config) = self
.workspaces_mut()
.find(|ws| ws.has_window(&window_id))
.map(|ws| {
+ let workspace_config = ws.layout_config().cloned().map(|c| (ws.id(), c));
(
ws.is_floating(&window_id),
ws.tiles_mut()
.find(|tile| *tile.window().id() == window_id)
.unwrap(),
+ workspace_config,
)
})
.unwrap();
@@ -3807,11 +3831,10 @@ impl<W: LayoutElement> Layout<W> {
let view_size = output_size(&output);
let scale = output.current_scale().fractional_scale();
- tile.update_config(
- view_size,
- scale,
- Rc::new(Options::clone(&self.options).adjusted_for_scale(scale)),
- );
+ let options = Options::clone(&self.options)
+ .with_merged_layout(workspace_config.as_ref().map(|(_, c)| c))
+ .adjusted_for_scale(scale);
+ tile.update_config(view_size, scale, Rc::new(options));
// Unfullscreen.
let floating_size = tile.floating_window_size;
@@ -3864,6 +3887,7 @@ impl<W: LayoutElement> Layout<W> {
is_full_width,
is_floating,
pointer_ratio_within_window,
+ workspace_config,
};
if let Some((tile_pos, zoom)) = tile_pos {
@@ -3880,6 +3904,23 @@ impl<W: LayoutElement> Layout<W> {
return false;
}
+ let mut ws_id = None;
+ if let Some(mon) = self.monitor_for_output(&output) {
+ let (insert_ws, _) = mon.insert_position(move_.pointer_pos_within_output);
+ if let InsertWorkspace::Existing(id) = insert_ws {
+ ws_id = Some(id);
+ }
+ }
+
+ // If moved over a different workspace, reset the config override.
+ let mut update_config = false;
+ if let Some((id, _)) = &move_.workspace_config {
+ if Some(*id) != ws_id {
+ move_.workspace_config = None;
+ update_config = true;
+ }
+ }
+
if output != move_.output {
move_.tile.window().output_leave(&move_.output);
move_.tile.window().output_enter(&output);
@@ -3887,15 +3928,18 @@ impl<W: LayoutElement> Layout<W> {
output.current_scale(),
output.current_transform(),
);
- let view_size = output_size(&output);
- let scale = output.current_scale().fractional_scale();
- move_.tile.update_config(
- view_size,
- scale,
- Rc::new(Options::clone(&self.options).adjusted_for_scale(scale)),
- );
move_.output = output.clone();
self.focus_output(&output);
+ update_config = true;
+ }
+
+ if update_config {
+ let view_size = output_size(&output);
+ let scale = output.current_scale().fractional_scale();
+ let options = Options::clone(&self.options)
+ .with_merged_layout(move_.workspace_config.as_ref().map(|(_, c)| c))
+ .adjusted_for_scale(scale);
+ move_.tile.update_config(view_size, scale, Rc::new(options));
}
move_.pointer_pos_within_output = pointer_pos_within_output;