diff --git a/komorebi-bar/src/config.rs b/komorebi-bar/src/config.rs index 21d67cf8..38fcea31 100644 --- a/komorebi-bar/src/config.rs +++ b/komorebi-bar/src/config.rs @@ -18,7 +18,7 @@ use std::path::PathBuf; /// The `komorebi.bar.json` configuration file reference for `v0.1.40` pub struct KomobarConfig { /// Bar height - #[cfg_attr(feature = "schemars", schemars(extend("default" = 50)))] + #[cfg_attr(feature = "schemars", schemars(extend("default" = 50.0)))] pub height: Option, /// Bar padding. Use one value for all sides or use a grouped padding for horizontal and/or /// vertical definition which can each take a single value for a symmetric padding or two diff --git a/komorebi/src/core/default_layout.rs b/komorebi/src/core/default_layout.rs index f4bd365a..47677a61 100644 --- a/komorebi/src/core/default_layout.rs +++ b/komorebi/src/core/default_layout.rs @@ -1,4 +1,5 @@ use clap::ValueEnum; +use core::str::FromStr; use serde::Deserialize; use serde::Serialize; use strum::Display; @@ -8,6 +9,22 @@ use super::OperationDirection; use super::Rect; use super::Sizing; +pub fn deserialize_option_none_default_layout<'de, D>( + deserializer: D, +) -> Result, D::Error> +where + D: serde::Deserializer<'de>, +{ + let s = String::deserialize(deserializer)?; + if s == "None" { + Ok(None) + } else { + ::from_str(&s) + .map(Some) + .map_err(serde::de::Error::custom) + } +} + #[derive( Clone, Copy, Debug, Serialize, Deserialize, Eq, PartialEq, Display, EnumString, ValueEnum, )] diff --git a/komorebi/src/lib.rs b/komorebi/src/lib.rs index 230dd2bc..bf97d4a5 100644 --- a/komorebi/src/lib.rs +++ b/komorebi/src/lib.rs @@ -240,6 +240,8 @@ lazy_static! { static ref CURRENT_VIRTUAL_DESKTOP: Arc>>> = Arc::new(Mutex::new(None)); } +pub static DEFAULT_WORKSPACE_LAYOUT: AtomicCell> = + AtomicCell::new(Some(DefaultLayout::BSP)); pub static DEFAULT_WORKSPACE_PADDING: AtomicI32 = AtomicI32::new(10); pub static DEFAULT_CONTAINER_PADDING: AtomicI32 = AtomicI32::new(10); pub static DEFAULT_RESIZE_DELTA: i32 = 50; diff --git a/komorebi/src/static_config.rs b/komorebi/src/static_config.rs index 34981f51..55d31b0b 100644 --- a/komorebi/src/static_config.rs +++ b/komorebi/src/static_config.rs @@ -5,6 +5,7 @@ use crate::DATA_DIR; use crate::DEFAULT_CONTAINER_PADDING; use crate::DEFAULT_MOUSE_FOLLOWS_FOCUS; use crate::DEFAULT_RESIZE_DELTA; +use crate::DEFAULT_WORKSPACE_LAYOUT; use crate::DEFAULT_WORKSPACE_PADDING; use crate::DISPLAY_INDEX_PREFERENCES; use crate::FLOATING_APPLICATIONS; @@ -557,6 +558,11 @@ pub struct StaticConfig { /// Individual window transparency ignore rules #[serde(skip_serializing_if = "Option::is_none")] pub transparency_ignore_rules: Option>, + /// Global default workspace layout for new workspaces + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "schemars", schemars(extend("default" = DefaultLayout::BSP)))] + #[serde(deserialize_with = "crate::default_layout::deserialize_option_none_default_layout")] + pub default_workspace_layout: Option, /// Global default workspace padding #[serde(skip_serializing_if = "Option::is_none")] #[cfg_attr(feature = "schemars", schemars(extend("default" = DEFAULT_WORKSPACE_PADDING)))] @@ -907,6 +913,7 @@ impl From<&WindowManager> for StaticConfig { remove_titlebar_applications: Option::from(NO_TITLEBAR.lock().clone()), floating_window_aspect_ratio: Option::from(*FLOATING_WINDOW_TOGGLE_ASPECT_RATIO.lock()), window_handling_behaviour: Option::from(WINDOW_HANDLING_BEHAVIOUR.load()), + default_workspace_layout: DEFAULT_WORKSPACE_LAYOUT.load(), } } } @@ -985,6 +992,8 @@ impl StaticConfig { DEFAULT_CONTAINER_PADDING.store(container, Ordering::SeqCst); } + DEFAULT_WORKSPACE_LAYOUT.store(self.default_workspace_layout); + if let Some(workspace) = self.default_workspace_padding { DEFAULT_WORKSPACE_PADDING.store(workspace, Ordering::SeqCst); } diff --git a/komorebi/src/window_manager.rs b/komorebi/src/window_manager.rs index abd7228c..aec210ad 100644 --- a/komorebi/src/window_manager.rs +++ b/komorebi/src/window_manager.rs @@ -3876,6 +3876,7 @@ impl WindowManager { #[cfg(test)] mod tests { use super::*; + use crate::DEFAULT_WORKSPACE_LAYOUT; use crate::monitor; use crossbeam_channel::Sender; use crossbeam_channel::bounded; @@ -5202,6 +5203,7 @@ mod tests { #[test] fn test_toggle_tiling() { let (mut wm, _context) = setup_window_manager(); + DEFAULT_WORKSPACE_LAYOUT.store(Some(DefaultLayout::BSP)); { let mut m = monitor::new( diff --git a/komorebi/src/workspace.rs b/komorebi/src/workspace.rs index 65c4062b..0112863c 100644 --- a/komorebi/src/workspace.rs +++ b/komorebi/src/workspace.rs @@ -8,6 +8,7 @@ use std::sync::atomic::Ordering; use crate::DATA_DIR; use crate::DEFAULT_CONTAINER_PADDING; +use crate::DEFAULT_WORKSPACE_LAYOUT; use crate::DEFAULT_WORKSPACE_PADDING; use crate::FloatingLayerBehaviour; use crate::INITIAL_CONFIGURATION_LOADED; @@ -107,6 +108,8 @@ impl_ring_elements!(Workspace, Window, "floating_window"); impl Default for Workspace { fn default() -> Self { + let default_layout = DEFAULT_WORKSPACE_LAYOUT.load(); + Self { name: None, containers: Ring::default(), @@ -115,7 +118,7 @@ impl Default for Workspace { maximized_window_restore_idx: None, monocle_container_restore_idx: None, floating_windows: Ring::default(), - layout: Layout::Default(DefaultLayout::BSP), + layout: Layout::Default(default_layout.unwrap_or(DefaultLayout::BSP)), layout_options: None, layout_rules: vec![], layout_flip: None, @@ -123,7 +126,7 @@ impl Default for Workspace { container_padding: Option::from(DEFAULT_CONTAINER_PADDING.load(Ordering::SeqCst)), latest_layout: vec![], resize_dimensions: vec![], - tile: true, + tile: default_layout.is_some(), work_area_offset: None, apply_window_based_work_area_offset: true, window_container_behaviour: None, diff --git a/schema.bar.json b/schema.bar.json index df4ab75f..1f808823 100644 --- a/schema.bar.json +++ b/schema.bar.json @@ -68,7 +68,7 @@ "null" ], "format": "float", - "default": 1.399999976158142 + "default": 1.4 }, "left_widgets": { "description": "Left side widgets (ordered left-to-right)", @@ -99,7 +99,15 @@ }, "monitor": { "description": "The monitor index or the full monitor options", - "$ref": "#/$defs/MonitorConfigOrIndex" + "anyOf": [ + { + "$ref": "#/$defs/MonitorConfigOrIndex" + }, + { + "type": "null" + } + ], + "default": 0 }, "mouse": { "description": "Options for mouse interaction on the bar", @@ -174,7 +182,6 @@ } }, "required": [ - "monitor", "left_widgets", "right_widgets" ], diff --git a/schema.json b/schema.json index 97760954..1fa2b30c 100644 --- a/schema.json +++ b/schema.json @@ -152,6 +152,18 @@ "format": "int32", "default": 10 }, + "default_workspace_layout": { + "description": "Global default workspace layout for new workspaces", + "anyOf": [ + { + "$ref": "#/$defs/DefaultLayout" + }, + { + "type": "null" + } + ], + "default": "BSP" + }, "default_workspace_padding": { "description": "Global default workspace padding", "type": [