diff --git a/cosmic-comp-config/src/lib.rs b/cosmic-comp-config/src/lib.rs index 83d3680f..529e1ae0 100644 --- a/cosmic-comp-config/src/lib.rs +++ b/cosmic-comp-config/src/lib.rs @@ -23,6 +23,8 @@ pub struct CosmicCompConfig { pub autotile_behavior: TileBehavior, /// Active hint enabled pub active_hint: bool, + /// Smart gaps enabled + pub smart_gaps: bool, } impl Default for CosmicCompConfig { @@ -48,6 +50,7 @@ impl Default for CosmicCompConfig { autotile: Default::default(), autotile_behavior: Default::default(), active_hint: true, + smart_gaps: Default::default(), } } } diff --git a/src/config/mod.rs b/src/config/mod.rs index d8a5e0fa..d68bed5e 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -651,6 +651,13 @@ fn config_changed(config: cosmic_config::Config, keys: Vec, state: &mut state.common.update_config(); } } + "smart_gaps" => { + let new = get_config::(&config, "smart_gaps"); + if new != state.common.config.cosmic_conf.smart_gaps { + state.common.config.cosmic_conf.smart_gaps = new; + state.common.update_config(); + } + } _ => {} } } diff --git a/src/shell/layout/tiling/grabs/resize.rs b/src/shell/layout/tiling/grabs/resize.rs index 2f908941..989122d3 100644 --- a/src/shell/layout/tiling/grabs/resize.rs +++ b/src/shell/layout/tiling/grabs/resize.rs @@ -224,6 +224,7 @@ impl ResizeForkGrab { let mut shell = data.common.shell.write().unwrap(); let tiling_layer = &mut shell.active_space_mut(&output).tiling_layer; let gaps = tiling_layer.gaps(); + let is_smart_gaps = data.common.config.cosmic_conf.smart_gaps; let tree = &mut tiling_layer.queue.trees.back_mut().unwrap().0; match &mut self.old_tree { @@ -317,7 +318,7 @@ impl ResizeForkGrab { } self.last_loc = location.as_global(); - let blocker = TilingLayout::update_positions(&output, tree, gaps); + let blocker = TilingLayout::update_positions(&output, tree, gaps, is_smart_gaps); tiling_layer.pending_blockers.extend(blocker); } else { return true; diff --git a/src/shell/layout/tiling/mod.rs b/src/shell/layout/tiling/mod.rs index ff32a950..621e18f0 100644 --- a/src/shell/layout/tiling/mod.rs +++ b/src/shell/layout/tiling/mod.rs @@ -134,6 +134,7 @@ pub struct TilingLayout { swapping_stack_surface_id: Id, last_overview_hover: Option<(Option, TargetZone)>, pub theme: cosmic::Theme, + smart_gaps: bool, } #[derive(Debug, Clone, PartialEq)] @@ -341,7 +342,7 @@ pub struct MinimizedTilingState { } impl TilingLayout { - pub fn new(theme: cosmic::Theme, output: &Output) -> TilingLayout { + pub fn new(theme: cosmic::Theme, output: &Output, smart_gaps: bool) -> TilingLayout { TilingLayout { queue: TreeQueue { trees: { @@ -357,6 +358,7 @@ impl TilingLayout { swapping_stack_surface_id: Id::new(), last_overview_hover: None, theme, + smart_gaps, } } @@ -376,7 +378,7 @@ impl TilingLayout { } } - let blocker = TilingLayout::update_positions(output, &mut tree, gaps); + let blocker = TilingLayout::update_positions(output, &mut tree, gaps, self.smart_gaps); self.queue.push_tree(tree, None, blocker); self.output = output.clone(); } @@ -419,7 +421,8 @@ impl TilingLayout { direction, minimize_rect, ); - let blocker = TilingLayout::update_positions(&self.output, &mut tree, gaps); + let blocker = + TilingLayout::update_positions(&self.output, &mut tree, gaps, self.smart_gaps); self.queue.push_tree(tree, duration, blocker); } @@ -484,7 +487,12 @@ impl TilingLayout { tree.make_nth_sibling(&new_id, idx).unwrap(); *window.tiling_node_id.lock().unwrap() = Some(new_id); - let blocker = TilingLayout::update_positions(&self.output, &mut tree, gaps); + let blocker = TilingLayout::update_positions( + &self.output, + &mut tree, + gaps, + self.smart_gaps, + ); self.queue .push_tree(tree, MINIMIZE_ANIMATION_DURATION, blocker); return; @@ -523,7 +531,8 @@ impl TilingLayout { *window.tiling_node_id.lock().unwrap() = Some(new_id); - let blocker = TilingLayout::update_positions(&self.output, &mut tree, gaps); + let blocker = + TilingLayout::update_positions(&self.output, &mut tree, gaps, self.smart_gaps); self.queue .push_tree(tree, MINIMIZE_ANIMATION_DURATION, blocker); return; @@ -628,7 +637,8 @@ impl TilingLayout { old.output_leave(&self.output); new.output_enter(&self.output, new.bbox()); - let blocker = TilingLayout::update_positions(&self.output, &mut tree, gaps); + let blocker = + TilingLayout::update_positions(&self.output, &mut tree, gaps, self.smart_gaps); self.queue.push_tree(tree, ANIMATION_DURATION, blocker); } } @@ -786,12 +796,20 @@ impl TilingLayout { let other_gaps = other.gaps(); TilingLayout::unmap_internal(&mut this_tree, &desc.node); - let blocker = - TilingLayout::update_positions(&this.output, &mut this_tree, this_gaps); + let blocker = TilingLayout::update_positions( + &this.output, + &mut this_tree, + this_gaps, + this.smart_gaps, + ); this.queue.push_tree(this_tree, ANIMATION_DURATION, blocker); - let blocker = - TilingLayout::update_positions(&other.output, &mut other_tree, other_gaps); + let blocker = TilingLayout::update_positions( + &other.output, + &mut other_tree, + other_gaps, + other.smart_gaps, + ); other .queue .push_tree(other_tree, ANIMATION_DURATION, blocker); @@ -1227,18 +1245,26 @@ impl TilingLayout { } let this_gaps = this.gaps(); - let blocker = TilingLayout::update_positions(&this.output, &mut this_tree, this_gaps); + let this_is_smart_gaps = this.smart_gaps; + let blocker = TilingLayout::update_positions( + &this.output, + &mut this_tree, + this_gaps, + this_is_smart_gaps, + ); this.queue.push_tree(this_tree, ANIMATION_DURATION, blocker); let has_other_tree = other_tree.is_some(); if let Some(mut other_tree) = other_tree { - let (other_queue, gaps) = if let Some(other) = other.as_mut() { + let (other_queue, gaps, is_smart_gaps) = if let Some(other) = other.as_mut() { let other_gaps = other.gaps(); - (&mut other.queue, other_gaps) + let other_is_smart_gaps = other.smart_gaps; + (&mut other.queue, other_gaps, other_is_smart_gaps) } else { - (&mut this.queue, this_gaps) + (&mut this.queue, this_gaps, this_is_smart_gaps) }; - let blocker = TilingLayout::update_positions(&other_output, &mut other_tree, gaps); + let blocker = + TilingLayout::update_positions(&other_output, &mut other_tree, gaps, is_smart_gaps); other_queue.push_tree(other_tree, ANIMATION_DURATION, blocker); } @@ -1394,7 +1420,8 @@ impl TilingLayout { } else { ANIMATION_DURATION }; - let blocker = TilingLayout::update_positions(&self.output, &mut tree, gaps); + let blocker = + TilingLayout::update_positions(&self.output, &mut tree, gaps, self.smart_gaps); self.queue.push_tree(tree, duration, blocker); return true; @@ -1513,7 +1540,12 @@ impl TilingLayout { .unwrap(); *mapped.tiling_node_id.lock().unwrap() = Some(new_id); - let blocker = TilingLayout::update_positions(&self.output, &mut tree, gaps); + let blocker = TilingLayout::update_positions( + &self.output, + &mut tree, + gaps, + self.smart_gaps, + ); self.queue.push_tree(tree, ANIMATION_DURATION, blocker); return MoveResult::ShiftFocus(mapped.into()); } @@ -1589,7 +1621,8 @@ impl TilingLayout { .data_mut() .remove_window(og_idx); - let blocker = TilingLayout::update_positions(&self.output, &mut tree, gaps); + let blocker = + TilingLayout::update_positions(&self.output, &mut tree, gaps, self.smart_gaps); self.queue.push_tree(tree, ANIMATION_DURATION, blocker); return MoveResult::Done; } @@ -1615,7 +1648,8 @@ impl TilingLayout { .data_mut() .remove_window(og_idx); - let blocker = TilingLayout::update_positions(&self.output, &mut tree, gaps); + let blocker = + TilingLayout::update_positions(&self.output, &mut tree, gaps, self.smart_gaps); self.queue.push_tree(tree, ANIMATION_DURATION, blocker); return MoveResult::Done; } @@ -1771,7 +1805,8 @@ impl TilingLayout { MoveResult::Done }; - let blocker = TilingLayout::update_positions(&self.output, &mut tree, gaps); + let blocker = + TilingLayout::update_positions(&self.output, &mut tree, gaps, self.smart_gaps); self.queue.push_tree(tree, ANIMATION_DURATION, blocker); return result; } @@ -2101,7 +2136,12 @@ impl TilingLayout { *orientation = new_orientation; - let blocker = TilingLayout::update_positions(&self.output, &mut tree, gaps); + let blocker = TilingLayout::update_positions( + &self.output, + &mut tree, + gaps, + self.smart_gaps, + ); self.queue.push_tree(tree, ANIMATION_DURATION, blocker); } } @@ -2219,7 +2259,8 @@ impl TilingLayout { } }; - let blocker = TilingLayout::update_positions(&self.output, &mut tree, gaps); + let blocker = + TilingLayout::update_positions(&self.output, &mut tree, gaps, self.smart_gaps); self.queue.push_tree(tree, ANIMATION_DURATION, blocker); Some(result) @@ -2295,7 +2336,12 @@ impl TilingLayout { minimize_rect: None, }; - let blocker = TilingLayout::update_positions(&self.output, &mut tree, gaps); + let blocker = TilingLayout::update_positions( + &self.output, + &mut tree, + gaps, + self.smart_gaps, + ); self.queue.push_tree(tree, ANIMATION_DURATION, blocker); return Some(KeyboardFocusTarget::Element(mapped)); @@ -2310,7 +2356,8 @@ impl TilingLayout { let gaps = self.gaps(); let mut tree = self.queue.trees.back().unwrap().0.copy_clone(); - let blocker = TilingLayout::update_positions(&self.output, &mut tree, gaps); + let blocker = + TilingLayout::update_positions(&self.output, &mut tree, gaps, self.smart_gaps); self.queue.push_tree(tree, ANIMATION_DURATION, blocker); } @@ -2580,7 +2627,8 @@ impl TilingLayout { } _ => unreachable!(), } - let blocker = TilingLayout::update_positions(&self.output, &mut tree, gaps); + let blocker = + TilingLayout::update_positions(&self.output, &mut tree, gaps, self.smart_gaps); self.queue.push_tree(tree, None, blocker); return true; @@ -2620,7 +2668,8 @@ impl TilingLayout { } } - let blocker = TilingLayout::update_positions(&self.output, &mut tree, gaps); + let blocker = + TilingLayout::update_positions(&self.output, &mut tree, gaps, self.smart_gaps); self.queue.push_tree(tree, ANIMATION_DURATION, blocker); } } @@ -2774,7 +2823,8 @@ impl TilingLayout { } } - let blocker = TilingLayout::update_positions(&self.output, &mut tree, gaps); + let blocker = + TilingLayout::update_positions(&self.output, &mut tree, gaps, self.smart_gaps); self.queue.push_tree(tree, ANIMATION_DURATION, blocker); let location = self.element_geometry(&mapped).unwrap().loc; @@ -2948,6 +2998,7 @@ impl TilingLayout { output: &Output, tree: &mut Tree, gaps: (i32, i32), + smart_gaps: bool, ) -> Option { if let Some(root_id) = tree.root_node_id() { let mut configures = Vec::new(); @@ -2956,10 +3007,15 @@ impl TilingLayout { let mut geo = layer_map_for_output(&output) .non_exclusive_zone() .as_local(); - geo.loc.x += outer; - geo.loc.y += outer; - geo.size.w -= outer * 2; - geo.size.h -= outer * 2; + + let root = tree.get(&root_id).unwrap(); + if !smart_gaps || root.data().is_group() { + geo.loc.x += outer; + geo.loc.y += outer; + geo.size.w -= outer * 2; + geo.size.h -= outer * 2; + } + let mut stack = vec![geo]; for node_id in tree @@ -3004,33 +3060,21 @@ impl TilingLayout { let node = tree.get(&node_id).unwrap(); let data = node.data(); if data.is_mapped(None) { + let calculate_gap = |dir| { + if TilingLayout::has_adjacent_node(tree, &node_id, dir) { + inner / 2 + } else if smart_gaps { + 0 + } else { + inner + } + }; + let gap = ( + (calculate_gap(Direction::Left), calculate_gap(Direction::Up)), ( - if TilingLayout::has_adjacent_node(tree, &node_id, Direction::Left) - { - inner / 2 - } else { - inner - }, - if TilingLayout::has_adjacent_node(tree, &node_id, Direction::Up) { - inner / 2 - } else { - inner - }, - ), - ( - if TilingLayout::has_adjacent_node(tree, &node_id, Direction::Right) - { - inner / 2 - } else { - inner - }, - if TilingLayout::has_adjacent_node(tree, &node_id, Direction::Down) - { - inner / 2 - } else { - inner - }, + calculate_gap(Direction::Right), + calculate_gap(Direction::Down), ), ); geo.loc += gap.0.into(); @@ -3122,6 +3166,7 @@ impl TilingLayout { overview: OverviewMode, ) -> Option<(PointerFocusTarget, Point)> { let gaps = self.gaps(); + let smart_gaps = self.smart_gaps; let last_overview_hover = &mut self.last_overview_hover; let placeholder_id = &self.placeholder_id; let tree = &self.queue.trees.back().unwrap().0; @@ -3697,6 +3742,7 @@ impl TilingLayout { &self.output, &mut tree, gaps, + smart_gaps, ); self.queue.push_tree(tree, duration, blocker); } @@ -3796,7 +3842,7 @@ impl TilingLayout { }; TilingLayout::merge_trees(src, &mut dst, orientation); - let blocker = TilingLayout::update_positions(&self.output, &mut dst, gaps); + let blocker = TilingLayout::update_positions(&self.output, &mut dst, gaps, self.smart_gaps); self.queue.push_tree(dst, ANIMATION_DURATION, blocker); } diff --git a/src/shell/mod.rs b/src/shell/mod.rs index f594891c..c6b79f82 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -307,6 +307,7 @@ pub struct WorkspaceSet { pub group: WorkspaceGroupHandle, idx: usize, tiling_enabled: bool, + smart_gaps: bool, output: Output, theme: cosmic::Theme, pub sticky_layer: FloatingLayout, @@ -320,6 +321,7 @@ fn create_workspace( group_handle: &WorkspaceGroupHandle, active: bool, tiling: bool, + smart_gaps: bool, theme: cosmic::Theme, ) -> Workspace { let workspace_handle = state @@ -339,7 +341,13 @@ fn create_workspace( &workspace_handle, [WorkspaceCapabilities::Activate].into_iter(), ); - Workspace::new(workspace_handle, output.clone(), tiling, theme.clone()) + Workspace::new( + workspace_handle, + output.clone(), + tiling, + smart_gaps, + theme.clone(), + ) } fn move_workspace_to_group( @@ -409,6 +417,7 @@ impl WorkspaceSet { output: &Output, idx: usize, tiling_enabled: bool, + smart_gaps: bool, theme: cosmic::Theme, ) -> WorkspaceSet { let group_handle = state.create_workspace_group(); @@ -419,6 +428,7 @@ impl WorkspaceSet { &group_handle, true, tiling_enabled, + smart_gaps, theme.clone(), ); workspace_set_idx(state, 1, idx, &workspace.handle); @@ -436,6 +446,7 @@ impl WorkspaceSet { group: group_handle, idx, tiling_enabled, + smart_gaps, theme, sticky_layer, minimized_windows: Vec::new(), @@ -543,6 +554,7 @@ impl WorkspaceSet { &self.group, false, self.tiling_enabled, + self.smart_gaps, self.theme.clone(), ); workspace_set_idx( @@ -607,6 +619,7 @@ pub struct Workspaces { mode: WorkspaceMode, autotile: bool, autotile_behavior: TileBehavior, + smart_gaps: bool, theme: cosmic::Theme, } @@ -619,6 +632,7 @@ impl Workspaces { mode: config.cosmic_conf.workspaces.workspace_mode, autotile: config.cosmic_conf.autotile, autotile_behavior: config.cosmic_conf.autotile_behavior, + smart_gaps: config.cosmic_conf.smart_gaps, theme, } } @@ -646,6 +660,7 @@ impl Workspaces { &output, self.sets.len(), self.autotile, + self.smart_gaps, self.theme.clone(), ) }); @@ -835,6 +850,7 @@ impl Workspaces { &set.group, false, config.cosmic_conf.autotile, + config.cosmic_conf.smart_gaps, self.theme.clone(), ), ); diff --git a/src/shell/workspace.rs b/src/shell/workspace.rs index 4037eed5..117dc0b2 100644 --- a/src/shell/workspace.rs +++ b/src/shell/workspace.rs @@ -236,9 +236,10 @@ impl Workspace { handle: WorkspaceHandle, output: Output, tiling_enabled: bool, + smart_gaps: bool, theme: cosmic::Theme, ) -> Workspace { - let tiling_layer = TilingLayout::new(theme.clone(), &output); + let tiling_layer = TilingLayout::new(theme.clone(), &output, smart_gaps); let floating_layer = FloatingLayout::new(theme, &output); let output_name = output.name();