mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-03-30 06:02:06 +02:00
feat(wm): add replace configuration socket message
This commit introduces a new SocketMessage, ReplaceConfiguration, which attempts to replace a running instance of WindowManager with another created from a (presumably) different komorebi.json file. This will likely be useful for people who have multiple different monitor setups that they connect and disconnect from throughout the day, but definitely needs more testing. An experimental sub-widget which calls this SocketMessage has been added to komorebi-bar to aid with initial testing.
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -2693,6 +2693,7 @@ dependencies = [
|
||||
"color-eyre",
|
||||
"crossbeam-channel",
|
||||
"dirs",
|
||||
"dunce",
|
||||
"eframe",
|
||||
"egui-phosphor",
|
||||
"font-loader",
|
||||
|
||||
@@ -14,6 +14,7 @@ clap = { version = "4", features = ["derive", "wrap_help"] }
|
||||
color-eyre = "0.6"
|
||||
crossbeam-channel = "0.5"
|
||||
dirs = { workspace = true }
|
||||
dunce = "1"
|
||||
eframe = "0.28"
|
||||
egui-phosphor = "0.6.0"
|
||||
font-loader = "0.11"
|
||||
|
||||
@@ -183,7 +183,7 @@ impl Komobar {
|
||||
|
||||
for (idx, widget_config) in config.left_widgets.iter().enumerate() {
|
||||
if let WidgetConfig::Komorebi(config) = widget_config {
|
||||
komorebi_widget = Some(Komorebi::from(*config));
|
||||
komorebi_widget = Some(Komorebi::from(config));
|
||||
komorebi_widget_idx = Some(idx);
|
||||
side = Some(Side::Left);
|
||||
}
|
||||
@@ -191,7 +191,7 @@ impl Komobar {
|
||||
|
||||
for (idx, widget_config) in config.right_widgets.iter().enumerate() {
|
||||
if let WidgetConfig::Komorebi(config) = widget_config {
|
||||
komorebi_widget = Some(Komorebi::from(*config));
|
||||
komorebi_widget = Some(Komorebi::from(config));
|
||||
komorebi_widget_idx = Some(idx);
|
||||
side = Some(Side::Right);
|
||||
}
|
||||
|
||||
@@ -16,21 +16,26 @@ use eframe::egui::Ui;
|
||||
use image::RgbaImage;
|
||||
use komorebi_client::CycleDirection;
|
||||
use komorebi_client::NotificationEvent;
|
||||
use komorebi_client::Rect;
|
||||
use komorebi_client::SocketMessage;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::BTreeMap;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
|
||||
pub struct KomorebiConfig {
|
||||
/// Configure the Workspaces widget
|
||||
pub workspaces: KomorebiWorkspacesConfig,
|
||||
/// Configure the Layout widget
|
||||
pub layout: KomorebiLayoutConfig,
|
||||
pub layout: Option<KomorebiLayoutConfig>,
|
||||
/// Configure the Focused Window widget
|
||||
pub focused_window: KomorebiFocusedWindowConfig,
|
||||
pub focused_window: Option<KomorebiFocusedWindowConfig>,
|
||||
/// Configure the Configuration Switcher widget
|
||||
pub configuration_switcher: Option<KomorebiConfigurationSwitcherConfig>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema)]
|
||||
@@ -55,8 +60,37 @@ pub struct KomorebiFocusedWindowConfig {
|
||||
pub show_icon: bool,
|
||||
}
|
||||
|
||||
impl From<KomorebiConfig> for Komorebi {
|
||||
fn from(value: KomorebiConfig) -> Self {
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
|
||||
pub struct KomorebiConfigurationSwitcherConfig {
|
||||
/// Enable the Komorebi Configurations widget
|
||||
pub enable: bool,
|
||||
/// A map of display friendly name => path to configuration.json
|
||||
pub configurations: BTreeMap<String, String>,
|
||||
}
|
||||
|
||||
impl From<&KomorebiConfig> for Komorebi {
|
||||
fn from(value: &KomorebiConfig) -> Self {
|
||||
let configuration_switcher =
|
||||
if let Some(configuration_switcher) = &value.configuration_switcher {
|
||||
let mut configuration_switcher = configuration_switcher.clone();
|
||||
for (_, location) in configuration_switcher.configurations.iter_mut() {
|
||||
if let Ok(expanded) = std::env::var("KOMOREBI_CONFIG_HOME") {
|
||||
*location = location.replace("$Env:KOMOREBI_CONFIG_HOME", &expanded);
|
||||
}
|
||||
|
||||
if let Ok(expanded) = std::env::var("USERPROFILE") {
|
||||
*location = location.replace("$Env:USERPROFILE", &expanded);
|
||||
}
|
||||
|
||||
*location = dunce::simplified(&PathBuf::from(location.clone()))
|
||||
.to_string_lossy()
|
||||
.to_string();
|
||||
}
|
||||
Some(configuration_switcher)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Self {
|
||||
komorebi_notification_state: Rc::new(RefCell::new(KomorebiNotificationState {
|
||||
selected_workspace: String::new(),
|
||||
@@ -67,10 +101,12 @@ impl From<KomorebiConfig> for Komorebi {
|
||||
workspaces: vec![],
|
||||
hide_empty_workspaces: value.workspaces.hide_empty_workspaces,
|
||||
mouse_follows_focus: true,
|
||||
work_area_offset: None,
|
||||
})),
|
||||
workspaces: value.workspaces,
|
||||
layout: value.layout,
|
||||
focused_window: value.focused_window,
|
||||
configuration_switcher,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -79,8 +115,9 @@ impl From<KomorebiConfig> for Komorebi {
|
||||
pub struct Komorebi {
|
||||
pub komorebi_notification_state: Rc<RefCell<KomorebiNotificationState>>,
|
||||
pub workspaces: KomorebiWorkspacesConfig,
|
||||
pub layout: KomorebiLayoutConfig,
|
||||
pub focused_window: KomorebiFocusedWindowConfig,
|
||||
pub layout: Option<KomorebiLayoutConfig>,
|
||||
pub focused_window: Option<KomorebiFocusedWindowConfig>,
|
||||
pub configuration_switcher: Option<KomorebiConfigurationSwitcherConfig>,
|
||||
}
|
||||
|
||||
impl BarWidget for Komorebi {
|
||||
@@ -103,9 +140,7 @@ impl BarWidget for Komorebi {
|
||||
.unwrap();
|
||||
komorebi_client::send_message(&SocketMessage::FocusWorkspaceNumber(i)).unwrap();
|
||||
komorebi_client::send_message(&SocketMessage::MouseFollowsFocus(
|
||||
self.komorebi_notification_state
|
||||
.borrow()
|
||||
.mouse_follows_focus,
|
||||
komorebi_notification_state.mouse_follows_focus,
|
||||
))
|
||||
.unwrap();
|
||||
komorebi_client::send_message(&SocketMessage::Retile).unwrap();
|
||||
@@ -119,36 +154,78 @@ impl BarWidget for Komorebi {
|
||||
ui.add_space(WIDGET_SPACING);
|
||||
}
|
||||
|
||||
if self.layout.enable {
|
||||
if ui
|
||||
.add(
|
||||
Label::new(&komorebi_notification_state.layout)
|
||||
.selectable(false)
|
||||
.sense(Sense::click()),
|
||||
)
|
||||
.clicked()
|
||||
{
|
||||
komorebi_client::send_message(&SocketMessage::CycleLayout(CycleDirection::Next))
|
||||
if let Some(layout) = self.layout {
|
||||
if layout.enable {
|
||||
if ui
|
||||
.add(
|
||||
Label::new(&komorebi_notification_state.layout)
|
||||
.selectable(false)
|
||||
.sense(Sense::click()),
|
||||
)
|
||||
.clicked()
|
||||
{
|
||||
komorebi_client::send_message(&SocketMessage::CycleLayout(
|
||||
CycleDirection::Next,
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
ui.add_space(WIDGET_SPACING);
|
||||
ui.add_space(WIDGET_SPACING);
|
||||
}
|
||||
}
|
||||
|
||||
if self.focused_window.enable {
|
||||
if self.focused_window.show_icon {
|
||||
if let Some(img) = &komorebi_notification_state.focused_window_icon {
|
||||
ui.add(
|
||||
Image::from(&img_to_texture(ctx, img))
|
||||
.maintain_aspect_ratio(true)
|
||||
.max_height(15.0),
|
||||
);
|
||||
if let Some(configuration_switcher) = &self.configuration_switcher {
|
||||
if configuration_switcher.enable {
|
||||
for (name, location) in configuration_switcher.configurations.iter() {
|
||||
let path = PathBuf::from(location);
|
||||
if path.is_file()
|
||||
&& ui
|
||||
.add(Label::new(name).selectable(false).sense(Sense::click()))
|
||||
.clicked()
|
||||
{
|
||||
let canonicalized = dunce::canonicalize(path.clone()).unwrap_or(path);
|
||||
komorebi_client::send_message(&SocketMessage::ReplaceConfiguration(
|
||||
canonicalized,
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
if let Some(rect) = komorebi_notification_state.work_area_offset {
|
||||
let monitor_index = komorebi_client::send_query(&SocketMessage::Query(
|
||||
komorebi_client::StateQuery::FocusedMonitorIndex,
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
komorebi_client::send_message(&SocketMessage::MonitorWorkAreaOffset(
|
||||
monitor_index.parse::<usize>().unwrap(),
|
||||
rect,
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui.add_space(WIDGET_SPACING);
|
||||
}
|
||||
}
|
||||
|
||||
ui.add(Label::new(&komorebi_notification_state.focused_window_title).selectable(false));
|
||||
if let Some(focused_window) = self.focused_window {
|
||||
if focused_window.enable {
|
||||
if focused_window.show_icon {
|
||||
if let Some(img) = &komorebi_notification_state.focused_window_icon {
|
||||
ui.add(
|
||||
Image::from(&img_to_texture(ctx, img))
|
||||
.maintain_aspect_ratio(true)
|
||||
.max_height(15.0),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ui.add_space(WIDGET_SPACING);
|
||||
ui.add(
|
||||
Label::new(&komorebi_notification_state.focused_window_title).selectable(false),
|
||||
);
|
||||
|
||||
ui.add_space(WIDGET_SPACING);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -170,6 +247,7 @@ pub struct KomorebiNotificationState {
|
||||
pub layout: String,
|
||||
pub hide_empty_workspaces: bool,
|
||||
pub mouse_follows_focus: bool,
|
||||
pub work_area_offset: Option<Rect>,
|
||||
}
|
||||
|
||||
impl KomorebiNotificationState {
|
||||
@@ -199,6 +277,9 @@ impl KomorebiNotificationState {
|
||||
self.mouse_follows_focus = notification.state.mouse_follows_focus;
|
||||
|
||||
let monitor = ¬ification.state.monitors.elements()[monitor_index];
|
||||
self.work_area_offset =
|
||||
notification.state.monitors.elements()[monitor_index].work_area_offset();
|
||||
|
||||
let focused_workspace_idx = monitor.focused_workspace_idx();
|
||||
|
||||
let mut workspaces = vec![];
|
||||
|
||||
@@ -41,7 +41,7 @@ impl WidgetConfig {
|
||||
match self {
|
||||
WidgetConfig::Battery(config) => Box::new(Battery::from(*config)),
|
||||
WidgetConfig::Date(config) => Box::new(Date::from(config.clone())),
|
||||
WidgetConfig::Komorebi(config) => Box::new(Komorebi::from(*config)),
|
||||
WidgetConfig::Komorebi(config) => Box::new(Komorebi::from(config)),
|
||||
WidgetConfig::Media(config) => Box::new(Media::from(*config)),
|
||||
WidgetConfig::Memory(config) => Box::new(Memory::from(*config)),
|
||||
WidgetConfig::Network(config) => Box::new(Network::from(*config)),
|
||||
|
||||
@@ -133,6 +133,7 @@ pub enum SocketMessage {
|
||||
ClearNamedWorkspaceLayoutRules(String),
|
||||
// Configuration
|
||||
ReloadConfiguration,
|
||||
ReplaceConfiguration(PathBuf),
|
||||
ReloadStaticConfiguration(PathBuf),
|
||||
WatchConfiguration(bool),
|
||||
CompleteConfiguration,
|
||||
|
||||
@@ -220,6 +220,7 @@ fn main() -> Result<()> {
|
||||
Arc::new(Mutex::new(StaticConfig::preload(
|
||||
config,
|
||||
winevent_listener::event_rx(),
|
||||
None,
|
||||
)?))
|
||||
} else {
|
||||
Arc::new(Mutex::new(WindowManager::new(
|
||||
|
||||
@@ -56,6 +56,7 @@ use crate::window::Window;
|
||||
use crate::window_manager;
|
||||
use crate::window_manager::WindowManager;
|
||||
use crate::windows_api::WindowsApi;
|
||||
use crate::winevent_listener;
|
||||
use crate::GlobalState;
|
||||
use crate::Notification;
|
||||
use crate::NotificationEvent;
|
||||
@@ -1097,6 +1098,33 @@ impl WindowManager {
|
||||
SocketMessage::ReloadConfiguration => {
|
||||
Self::reload_configuration();
|
||||
}
|
||||
SocketMessage::ReplaceConfiguration(ref config) => {
|
||||
// Check that this is a valid static config file first
|
||||
if StaticConfig::read(config).is_ok() {
|
||||
// Clear workspace rules; these will need to be replaced
|
||||
WORKSPACE_RULES.lock().clear();
|
||||
// Pause so that restored windows come to the foreground from all workspaces
|
||||
self.is_paused = true;
|
||||
// Bring all windows to the foreground
|
||||
self.restore_all_windows()?;
|
||||
|
||||
// Create a new wm from the config path
|
||||
let mut wm = StaticConfig::preload(
|
||||
config,
|
||||
winevent_listener::event_rx(),
|
||||
self.command_listener.try_clone().ok(),
|
||||
)?;
|
||||
|
||||
// Initialize the new wm
|
||||
wm.init()?;
|
||||
|
||||
// This is equivalent to StaticConfig::postload for this use case
|
||||
StaticConfig::reload(config, &mut wm)?;
|
||||
|
||||
// Set self to the new wm instance
|
||||
*self = wm;
|
||||
}
|
||||
}
|
||||
SocketMessage::ReloadStaticConfiguration(ref pathbuf) => {
|
||||
self.reload_static_configuration(pathbuf)?;
|
||||
}
|
||||
|
||||
@@ -1027,26 +1027,32 @@ impl StaticConfig {
|
||||
pub fn preload(
|
||||
path: &PathBuf,
|
||||
incoming: Receiver<WindowManagerEvent>,
|
||||
unix_listener: Option<UnixListener>,
|
||||
) -> Result<WindowManager> {
|
||||
let content = std::fs::read_to_string(path)?;
|
||||
let mut value: Self = serde_json::from_str(&content)?;
|
||||
value.apply_globals()?;
|
||||
|
||||
let socket = DATA_DIR.join("komorebi.sock");
|
||||
let listener = match unix_listener {
|
||||
Some(listener) => listener,
|
||||
None => {
|
||||
let socket = DATA_DIR.join("komorebi.sock");
|
||||
|
||||
match std::fs::remove_file(&socket) {
|
||||
Ok(()) => {}
|
||||
Err(error) => match error.kind() {
|
||||
// Doing this because ::exists() doesn't work reliably on Windows via IntelliJ
|
||||
ErrorKind::NotFound => {}
|
||||
_ => {
|
||||
return Err(error.into());
|
||||
}
|
||||
},
|
||||
match std::fs::remove_file(&socket) {
|
||||
Ok(()) => {}
|
||||
Err(error) => match error.kind() {
|
||||
// Doing this because ::exists() doesn't work reliably on Windows via IntelliJ
|
||||
ErrorKind::NotFound => {}
|
||||
_ => {
|
||||
return Err(error.into());
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
UnixListener::bind(&socket)?
|
||||
}
|
||||
};
|
||||
|
||||
let listener = UnixListener::bind(&socket)?;
|
||||
|
||||
let mut wm = WindowManager {
|
||||
monitors: Ring::default(),
|
||||
incoming_events: incoming,
|
||||
|
||||
@@ -861,6 +861,12 @@ struct EnableAutostart {
|
||||
ahk: bool,
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
struct ReplaceConfiguration {
|
||||
/// Static configuration JSON file from which the configuration should be loaded
|
||||
path: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
#[clap(author, about, version = build::CLAP_LONG_VERSION)]
|
||||
struct Opts {
|
||||
@@ -1168,12 +1174,15 @@ enum SubCommand {
|
||||
Manage,
|
||||
/// Unmanage a window that was forcibly managed
|
||||
Unmanage,
|
||||
/// Reload ~/komorebi.ahk (if it exists)
|
||||
/// Replace the configuration of a running instance of komorebi from a static configuration file
|
||||
#[clap(arg_required_else_help = true)]
|
||||
ReplaceConfiguration(ReplaceConfiguration),
|
||||
/// Reload legacy komorebi.ahk or komorebi.ps1 configurations (if they exist)
|
||||
ReloadConfiguration,
|
||||
/// Enable or disable watching of ~/komorebi.ahk (if it exists)
|
||||
/// Enable or disable watching of legacy komorebi.ahk or komorebi.ps1 configurations (if they exist)
|
||||
#[clap(arg_required_else_help = true)]
|
||||
WatchConfiguration(WatchConfiguration),
|
||||
/// Signal that the final configuration option has been sent
|
||||
/// For legacy komorebi.ahk or komorebi.ps1 configurations, signal that the final configuration option has been sent
|
||||
CompleteConfiguration,
|
||||
/// DEPRECATED since v0.1.22
|
||||
#[clap(arg_required_else_help = true)]
|
||||
@@ -1518,7 +1527,7 @@ fn main() -> Result<()> {
|
||||
// Check that this file adheres to the schema static config schema as the last step,
|
||||
// so that more basic errors above can be shown to the error before schema-specific
|
||||
// errors
|
||||
let _ = serde_json::from_str::<komorebi_client::StaticConfig>(&config_source)?;
|
||||
let _ = serde_json::from_str::<StaticConfig>(&config_source)?;
|
||||
|
||||
if config_whkd.exists() {
|
||||
println!("Found {}; key bindings will be loaded from here when whkd is started, and you can start it automatically using the --whkd flag\n", config_whkd.to_string_lossy());
|
||||
@@ -2283,6 +2292,9 @@ Stop-Process -Name:komorebi -ErrorAction SilentlyContinue
|
||||
arg.boolean_state.into(),
|
||||
))?;
|
||||
}
|
||||
SubCommand::ReplaceConfiguration(arg) => {
|
||||
send_message(&SocketMessage::ReplaceConfiguration(arg.path))?;
|
||||
}
|
||||
SubCommand::ReloadConfiguration => {
|
||||
send_message(&SocketMessage::ReloadConfiguration)?;
|
||||
}
|
||||
|
||||
@@ -150,11 +150,30 @@
|
||||
"Komorebi": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"focused_window",
|
||||
"layout",
|
||||
"workspaces"
|
||||
],
|
||||
"properties": {
|
||||
"configuration_switcher": {
|
||||
"description": "Configure the Configuration Switcher widget",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"configurations",
|
||||
"enable"
|
||||
],
|
||||
"properties": {
|
||||
"configurations": {
|
||||
"description": "A map of display friendly name => path to configuration.json",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"enable": {
|
||||
"description": "Enable the Komorebi Configurations widget",
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"focused_window": {
|
||||
"description": "Configure the Focused Window widget",
|
||||
"type": "object",
|
||||
@@ -540,11 +559,30 @@
|
||||
"Komorebi": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"focused_window",
|
||||
"layout",
|
||||
"workspaces"
|
||||
],
|
||||
"properties": {
|
||||
"configuration_switcher": {
|
||||
"description": "Configure the Configuration Switcher widget",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"configurations",
|
||||
"enable"
|
||||
],
|
||||
"properties": {
|
||||
"configurations": {
|
||||
"description": "A map of display friendly name => path to configuration.json",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"enable": {
|
||||
"description": "Enable the Komorebi Configurations widget",
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"focused_window": {
|
||||
"description": "Configure the Focused Window widget",
|
||||
"type": "object",
|
||||
|
||||
82
schema.json
82
schema.json
@@ -1320,9 +1320,41 @@
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name",
|
||||
"type"
|
||||
"palette"
|
||||
],
|
||||
"properties": {
|
||||
"bar_accent": {
|
||||
"description": "Komorebi status bar accent (default: Blue)",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Rosewater",
|
||||
"Flamingo",
|
||||
"Pink",
|
||||
"Mauve",
|
||||
"Red",
|
||||
"Maroon",
|
||||
"Peach",
|
||||
"Yellow",
|
||||
"Green",
|
||||
"Teal",
|
||||
"Sky",
|
||||
"Sapphire",
|
||||
"Blue",
|
||||
"Lavender",
|
||||
"Text",
|
||||
"Subtext1",
|
||||
"Subtext0",
|
||||
"Overlay2",
|
||||
"Overlay1",
|
||||
"Overlay0",
|
||||
"Surface2",
|
||||
"Surface1",
|
||||
"Surface0",
|
||||
"Base",
|
||||
"Mantle",
|
||||
"Crust"
|
||||
]
|
||||
},
|
||||
"monocle_border": {
|
||||
"description": "Border colour when the container is in monocle mode (default: Pink)",
|
||||
"type": "string",
|
||||
@@ -1365,6 +1397,12 @@
|
||||
"Mocha"
|
||||
]
|
||||
},
|
||||
"palette": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Catppuccin"
|
||||
]
|
||||
},
|
||||
"single_border": {
|
||||
"description": "Border colour when the container contains a single window (default: Blue)",
|
||||
"type": "string",
|
||||
@@ -1525,12 +1563,6 @@
|
||||
"Crust"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Catppuccin"
|
||||
]
|
||||
},
|
||||
"unfocused_border": {
|
||||
"description": "Border colour when the container is unfocused (default: Base)",
|
||||
"type": "string",
|
||||
@@ -1570,9 +1602,31 @@
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name",
|
||||
"type"
|
||||
"palette"
|
||||
],
|
||||
"properties": {
|
||||
"bar_accent": {
|
||||
"description": "Komorebi status bar accent (default: Base0D)",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Base00",
|
||||
"Base01",
|
||||
"Base02",
|
||||
"Base03",
|
||||
"Base04",
|
||||
"Base05",
|
||||
"Base06",
|
||||
"Base07",
|
||||
"Base08",
|
||||
"Base09",
|
||||
"Base0A",
|
||||
"Base0B",
|
||||
"Base0C",
|
||||
"Base0D",
|
||||
"Base0E",
|
||||
"Base0F"
|
||||
]
|
||||
},
|
||||
"monocle_border": {
|
||||
"description": "Border colour when the container is in monocle mode (default: Base0F)",
|
||||
"type": "string",
|
||||
@@ -1870,6 +1924,12 @@
|
||||
"Zenburn"
|
||||
]
|
||||
},
|
||||
"palette": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Base16"
|
||||
]
|
||||
},
|
||||
"single_border": {
|
||||
"description": "Border colour when the container contains a single window (default: Base0D)",
|
||||
"type": "string",
|
||||
@@ -1980,12 +2040,6 @@
|
||||
"Base0F"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Base16"
|
||||
]
|
||||
},
|
||||
"unfocused_border": {
|
||||
"description": "Border colour when the container is unfocused (default: Base01)",
|
||||
"type": "string",
|
||||
|
||||
Reference in New Issue
Block a user