feat(wm): add theme socket message

This commit adds a new SocketMessage::Theme which allows for themes to
be set programmatically. This change has also been plumbed through to
komorebi-bar so that the bar theme will also update after komorebi
processes the message and passes it on to subscribers.

A new theme_manager module has been introduced to add notification-based
handling of theme changes, both from the static config file being
updated and from SocketMessage::Theme being received.
This commit is contained in:
LGUG2Z
2024-10-16 14:19:55 -07:00
parent 1ef7a09163
commit 34929f32a7
14 changed files with 370 additions and 240 deletions

134
Cargo.lock generated
View File

@@ -556,9 +556,9 @@ dependencies = [
[[package]]
name = "avif-serialize"
version = "0.8.1"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "876c75a42f6364451a033496a14c44bffe41f5f4a8236f697391f11024e596d2"
checksum = "e335041290c43101ca215eed6f43ec437eb5a42125573f600fc3fa42b9bddd62"
dependencies = [
"arrayvec",
]
@@ -590,11 +590,13 @@ dependencies = [
[[package]]
name = "base16-egui-themes"
version = "0.1.0"
source = "git+https://github.com/LGUG2Z/base16-egui-themes?rev=57c38257cb0c6434321320d3746049bd58c34674#57c38257cb0c6434321320d3746049bd58c34674"
source = "git+https://github.com/LGUG2Z/base16-egui-themes?rev=c11fbe2a3a4681485c5065b899a4c4d85fad3b04#c11fbe2a3a4681485c5065b899a4c4d85fad3b04"
dependencies = [
"egui",
"schemars",
"serde",
"strum",
"strum_macros",
]
[[package]]
@@ -717,9 +719,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "bytemuck"
version = "1.18.0"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae"
checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d"
dependencies = [
"bytemuck_derive",
]
@@ -782,16 +784,17 @@ dependencies = [
[[package]]
name = "catppuccin-egui"
version = "5.3.0"
source = "git+https://github.com/LGUG2Z/catppuccin-egui?rev=f579847bf2f552b144361d5a78ed8cf360b55cbb#f579847bf2f552b144361d5a78ed8cf360b55cbb"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a2413b3bbc4e1b627b453d9147c156076b74f78e102e90797463bab0486eee6"
dependencies = [
"egui",
]
[[package]]
name = "cc"
version = "1.1.28"
version = "1.1.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1"
checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945"
dependencies = [
"jobserver",
"libc",
@@ -1644,7 +1647,7 @@ checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586"
dependencies = [
"cfg-if 1.0.0",
"libc",
"libredox 0.1.3",
"libredox",
"windows-sys 0.59.0",
]
@@ -2235,9 +2238,9 @@ checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946"
[[package]]
name = "hyper"
version = "1.4.1"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05"
checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a"
dependencies = [
"bytes",
"futures-channel",
@@ -2340,9 +2343,9 @@ dependencies = [
[[package]]
name = "image"
version = "0.25.2"
version = "0.25.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99314c8a2152b8ddb211f924cdae532d8c5e4c8bb54728e12fff1b0cd5963a10"
checksum = "d97eb9a8e0cd5b76afea91d7eecd5cf8338cd44ced04256cf1f800474b227c52"
dependencies = [
"bytemuck",
"byteorder-lite",
@@ -2363,9 +2366,9 @@ dependencies = [
[[package]]
name = "image-webp"
version = "0.1.3"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f79afb8cbee2ef20f59ccd477a218c12a93943d075b492015ecb1bb81f8ee904"
checksum = "e031e8e3d94711a9ccb5d6ea357439ef3dcbed361798bd4071dc4d9793fbe22f"
dependencies = [
"byteorder-lite",
"quick-error",
@@ -2373,9 +2376,9 @@ dependencies = [
[[package]]
name = "imgref"
version = "1.10.1"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44feda355f4159a7c757171a77de25daf6411e217b4cabd03bd6650690468126"
checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408"
[[package]]
name = "immutable-chunkmap"
@@ -2511,9 +2514,9 @@ checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0"
[[package]]
name = "js-sys"
version = "0.3.71"
version = "0.3.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0cb94a0ffd3f3ee755c20f7d8752f45cac88605a4dcf808abcff72873296ec7b"
checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9"
dependencies = [
"wasm-bindgen",
]
@@ -2645,6 +2648,8 @@ dependencies = [
"eframe",
"schemars",
"serde",
"serde_variant",
"strum",
]
[[package]]
@@ -2757,17 +2762,6 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "libredox"
version = "0.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607"
dependencies = [
"bitflags 2.6.0",
"libc",
"redox_syscall 0.4.1",
]
[[package]]
name = "libredox"
version = "0.1.3"
@@ -3611,9 +3605,9 @@ checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
[[package]]
name = "openssl"
version = "0.10.66"
version = "0.10.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1"
checksum = "7b8cefcf97f41316955f9294cd61f639bdcfa9f2f230faac6cb896aa8ab64704"
dependencies = [
"bitflags 2.6.0",
"cfg-if 1.0.0",
@@ -3643,9 +3637,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-sys"
version = "0.9.103"
version = "0.9.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6"
checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741"
dependencies = [
"cc",
"libc",
@@ -3661,11 +3655,11 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
name = "orbclient"
version = "0.3.47"
version = "0.3.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52f0d54bde9774d3a51dcf281a5def240c71996bc6ca05d2c847ec8b2b216166"
checksum = "ba0b26cec2e24f08ed8bb31519a9333140a6599b867dac464bb150bdb796fd43"
dependencies = [
"libredox 0.0.2",
"libredox",
]
[[package]]
@@ -3920,27 +3914,27 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.87"
version = "1.0.88"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a"
checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9"
dependencies = [
"unicode-ident",
]
[[package]]
name = "profiling"
version = "1.0.15"
version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58"
checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d"
dependencies = [
"profiling-procmacros",
]
[[package]]
name = "profiling-procmacros"
version = "1.0.15"
version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd"
checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30"
dependencies = [
"quote",
"syn 2.0.79",
@@ -4142,7 +4136,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
dependencies = [
"getrandom",
"libredox 0.1.3",
"libredox",
"thiserror",
]
@@ -4245,9 +4239,6 @@ name = "rgb"
version = "0.8.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a"
dependencies = [
"bytemuck",
]
[[package]]
name = "ring"
@@ -4291,9 +4282,9 @@ dependencies = [
[[package]]
name = "rustls"
version = "0.23.14"
version = "0.23.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8"
checksum = "5fbb44d7acc4e873d613422379f69f237a1b141928c02f6bc6ccfddddc2d7993"
dependencies = [
"once_cell",
"rustls-pki-types",
@@ -4313,9 +4304,9 @@ dependencies = [
[[package]]
name = "rustls-pki-types"
version = "1.9.0"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55"
checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b"
[[package]]
name = "rustls-webpki"
@@ -4330,9 +4321,9 @@ dependencies = [
[[package]]
name = "rustversion"
version = "1.0.17"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248"
[[package]]
name = "ryu"
@@ -4516,6 +4507,15 @@ dependencies = [
"serde",
]
[[package]]
name = "serde_variant"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a0068df419f9d9b6488fdded3f1c818522cdea328e02ce9d9f147380265a432"
dependencies = [
"serde",
]
[[package]]
name = "serde_yaml"
version = "0.9.34+deprecated"
@@ -5457,9 +5457,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.94"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef073ced962d62984fb38a36e5fdc1a2b23c9e0e1fa0689bb97afa4202ef6887"
checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e"
dependencies = [
"cfg-if 1.0.0",
"once_cell",
@@ -5468,9 +5468,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.94"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4bfab14ef75323f4eb75fa52ee0a3fb59611977fd3240da19b2cf36ff85030e"
checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358"
dependencies = [
"bumpalo",
"log",
@@ -5483,9 +5483,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.44"
version = "0.4.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65471f79c1022ffa5291d33520cbbb53b7687b01c2f8e83b57d102eed7ed479d"
checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b"
dependencies = [
"cfg-if 1.0.0",
"js-sys",
@@ -5495,9 +5495,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.94"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7bec9830f60924d9ceb3ef99d55c155be8afa76954edffbb5936ff4509474e7"
checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -5505,9 +5505,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.94"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c74f6e152a76a2ad448e223b0fc0b6b5747649c3d769cc6bf45737bf97d0ed6"
checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
dependencies = [
"proc-macro2",
"quote",
@@ -5518,9 +5518,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.94"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a42f6c679374623f295a8623adfe63d9284091245c3504bde47c17a3ce2777d9"
checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d"
[[package]]
name = "wayland-backend"
@@ -5633,9 +5633,9 @@ dependencies = [
[[package]]
name = "web-sys"
version = "0.3.71"
version = "0.3.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44188d185b5bdcae1052d08bcbcf9091a5524038d4572cc4f4f2bb9d5554ddd9"
checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112"
dependencies = [
"js-sys",
"wasm-bindgen",

View File

@@ -26,17 +26,17 @@ install:
run target:
cargo +stable run --bin {{ target }} --locked
warn $RUST_LOG="warn":
just run
warn target $RUST_LOG="warn":
just run {{ target }}
info $RUST_LOG="info":
just run
info target $RUST_LOG="info":
just run {{ target }}
debug $RUST_LOG="debug":
just run
debug target $RUST_LOG="debug":
just run {{ target }}
trace $RUST_LOG="trace":
just run
trace target $RUST_LOG="trace":
just run {{ target }}
deadlock $RUST_LOG="trace":
cargo +stable run --bin komorebi --locked --features deadlock_detection

View File

@@ -136,11 +136,13 @@ impl From<Position> for Pos2 {
pub enum KomobarTheme {
/// A theme from catppuccin-egui
Catppuccin {
/// Name of the Catppuccin theme (theme previews: https://github.com/catppuccin/catppuccin)
name: komorebi_themes::Catppuccin,
accent: Option<komorebi_themes::CatppuccinValue>,
},
/// A theme from base16-egui-themes
Base16 {
/// Name of the Base16 theme (theme previews: https://tinted-theming.github.io/base16-gallery)
name: komorebi_themes::Base16,
accent: Option<komorebi_themes::Base16Value>,
},

View File

@@ -451,15 +451,23 @@ impl KomorebiNotificationState {
}
},
Ok(notification) => {
if let NotificationEvent::Socket(SocketMessage::ReloadStaticConfiguration(path)) =
notification.event
{
if let Ok(config) = komorebi_client::StaticConfig::read(&path) {
if let Some(theme) = config.theme {
apply_theme(ctx, KomobarTheme::from(theme), bg_color);
tracing::info!("applied theme from updated komorebi.json");
match notification.event {
NotificationEvent::WindowManager(_) => {}
NotificationEvent::Socket(message) => match message {
SocketMessage::ReloadStaticConfiguration(path) => {
if let Ok(config) = komorebi_client::StaticConfig::read(&path) {
if let Some(theme) = config.theme {
apply_theme(ctx, KomobarTheme::from(theme), bg_color.clone());
tracing::info!("applied theme from updated komorebi.json");
}
}
}
}
SocketMessage::Theme(theme) => {
apply_theme(ctx, KomobarTheme::from(theme), bg_color);
tracing::info!("applied theme from komorebi socket message");
}
_ => {}
},
}
self.mouse_follows_focus = notification.state.mouse_follows_focus;

View File

@@ -4,9 +4,11 @@ version = "0.1.30"
edition = "2021"
[dependencies]
base16-egui-themes = { git = "https://github.com/LGUG2Z/base16-egui-themes", rev = "57c38257cb0c6434321320d3746049bd58c34674" }
catppuccin-egui = { git = "https://github.com/LGUG2Z/catppuccin-egui", rev = "f579847bf2f552b144361d5a78ed8cf360b55cbb" }
#catppuccin-egui = { version = "5", default-features = false, features = ["egui28"] }
base16-egui-themes = { git = "https://github.com/LGUG2Z/base16-egui-themes", rev = "c11fbe2a3a4681485c5065b899a4c4d85fad3b04" }
#catppuccin-egui = { git = "https://github.com/LGUG2Z/catppuccin-egui", rev = "f579847bf2f552b144361d5a78ed8cf360b55cbb" }
catppuccin-egui = { version = "5", default-features = false, features = ["egui29"] }
eframe = { workspace = true }
schemars = { workspace = true }
serde = { workspace = true }
serde_variant = "0.1"
strum = "0.26"

View File

@@ -4,10 +4,12 @@
use schemars::JsonSchema;
use serde::Deserialize;
use serde::Serialize;
use strum::IntoEnumIterator;
pub use base16_egui_themes::Base16;
pub use catppuccin_egui;
pub use eframe::egui::Color32;
use serde_variant::to_variant_name;
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type")]
@@ -24,6 +26,28 @@ pub enum Theme {
},
}
impl Theme {
pub fn variant_names(&self) -> Vec<String> {
match self {
Theme::Catppuccin { .. } => {
vec![
"Frappe".to_string(),
"Latte".to_string(),
"Macchiato".to_string(),
"Mocha".to_string(),
]
}
Theme::Base16 { .. } => Base16::iter()
.map(|variant| {
to_variant_name(&variant)
.expect("could not convert to variant name")
.to_string()
})
.collect(),
}
}
}
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]
pub enum Base16Value {
Base00,

View File

@@ -14,6 +14,7 @@ use serde::Serialize;
use strum::Display;
use strum::EnumString;
use crate::KomorebiTheme;
pub use animation::AnimationStyle;
pub use arrangement::Arrangement;
pub use arrangement::Axis;
@@ -143,6 +144,7 @@ pub enum SocketMessage {
WatchConfiguration(bool),
CompleteConfiguration,
AltFocusHack(bool),
Theme(KomorebiTheme),
Animation(bool),
AnimationDuration(u64),
AnimationFps(u64),

View File

@@ -20,6 +20,7 @@ pub mod set_window_position;
pub mod stackbar_manager;
pub mod static_config;
pub mod styles;
pub mod theme_manager;
pub mod transparency_manager;
pub mod window;
pub mod window_manager;
@@ -300,10 +301,12 @@ pub struct Notification {
}
pub fn notify_subscribers(notification: Notification, state_has_been_modified: bool) -> Result<()> {
let is_subscription_event = matches!(
let is_override_event = matches!(
notification.event,
NotificationEvent::Socket(SocketMessage::AddSubscriberSocket(_))
| NotificationEvent::Socket(SocketMessage::AddSubscriberSocketWithOptions(_, _))
| NotificationEvent::Socket(SocketMessage::Theme(_))
| NotificationEvent::Socket(SocketMessage::ReloadStaticConfiguration(_))
);
let notification = &serde_json::to_string(&notification)?;
@@ -318,7 +321,7 @@ pub fn notify_subscribers(notification: Notification, state_has_been_modified: b
.unwrap_or_default()
.filter_state_changes;
if !apply_state_filter || state_has_been_modified || is_subscription_event {
if !apply_state_filter || state_has_been_modified || is_override_event {
match UnixStream::connect(path) {
Ok(mut stream) => {
tracing::debug!("pushed notification to subscriber: {socket}");

View File

@@ -38,6 +38,7 @@ use komorebi::process_movement::listen_for_movements;
use komorebi::reaper;
use komorebi::stackbar_manager;
use komorebi::static_config::StaticConfig;
use komorebi::theme_manager;
use komorebi::transparency_manager;
use komorebi::window_manager::WindowManager;
use komorebi::windows_api::WindowsApi;
@@ -271,6 +272,7 @@ fn main() -> Result<()> {
monitor_reconciliator::listen_for_notifications(wm.clone())?;
reaper::watch_for_orphans(wm.clone());
focus_manager::listen_for_notifications(wm.clone());
theme_manager::listen_for_notifications();
let (ctrlc_sender, ctrlc_receiver) = crossbeam_channel::bounded(1);
ctrlc::set_handler(move || {

View File

@@ -51,6 +51,7 @@ use crate::stackbar_manager;
use crate::stackbar_manager::STACKBAR_FONT_FAMILY;
use crate::stackbar_manager::STACKBAR_FONT_SIZE;
use crate::static_config::StaticConfig;
use crate::theme_manager;
use crate::transparency_manager;
use crate::window::RuleDebug;
use crate::window::Window;
@@ -1588,6 +1589,9 @@ impl WindowManager {
reply.write_all(schema.as_bytes())?;
}
SocketMessage::Theme(theme) => {
theme_manager::send_notification(theme);
}
// Deprecated commands
SocketMessage::AltFocusHack(_)
| SocketMessage::IdentifyBorderOverflowApplication(_, _) => {}

View File

@@ -20,6 +20,7 @@ use crate::stackbar_manager::STACKBAR_TAB_BACKGROUND_COLOUR;
use crate::stackbar_manager::STACKBAR_TAB_HEIGHT;
use crate::stackbar_manager::STACKBAR_TAB_WIDTH;
use crate::stackbar_manager::STACKBAR_UNFOCUSED_TEXT_COLOUR;
use crate::theme_manager;
use crate::transparency_manager;
use crate::window;
use crate::window_manager::WindowManager;
@@ -386,7 +387,7 @@ pub struct AnimationsConfig {
pub enum KomorebiTheme {
/// A theme from catppuccin-egui
Catppuccin {
/// Name of the Catppuccin theme
/// Name of the Catppuccin theme (theme previews: https://github.com/catppuccin/catppuccin)
name: komorebi_themes::Catppuccin,
/// Border colour when the container contains a single window (default: Blue)
single_border: Option<komorebi_themes::CatppuccinValue>,
@@ -409,7 +410,7 @@ pub enum KomorebiTheme {
},
/// A theme from base16-egui-themes
Base16 {
/// Name of the Base16 theme
/// Name of the Base16 theme (theme previews: https://tinted-theming.github.io/base16-gallery)
name: komorebi_themes::Base16,
/// Border colour when the container contains a single window (default: Base0D)
single_border: Option<komorebi_themes::Base16Value>,
@@ -815,151 +816,7 @@ impl StaticConfig {
}
if let Some(theme) = &self.theme {
let (
single_border,
stack_border,
monocle_border,
floating_border,
unfocused_border,
stackbar_focused_text,
stackbar_unfocused_text,
stackbar_background,
) = match theme {
KomorebiTheme::Catppuccin {
name,
single_border,
stack_border,
monocle_border,
floating_border,
unfocused_border,
stackbar_focused_text,
stackbar_unfocused_text,
stackbar_background,
..
} => {
let single_border = single_border
.unwrap_or(komorebi_themes::CatppuccinValue::Blue)
.color32(name.as_theme());
let stack_border = stack_border
.unwrap_or(komorebi_themes::CatppuccinValue::Green)
.color32(name.as_theme());
let monocle_border = monocle_border
.unwrap_or(komorebi_themes::CatppuccinValue::Pink)
.color32(name.as_theme());
let floating_border = floating_border
.unwrap_or(komorebi_themes::CatppuccinValue::Yellow)
.color32(name.as_theme());
let unfocused_border = unfocused_border
.unwrap_or(komorebi_themes::CatppuccinValue::Base)
.color32(name.as_theme());
let stackbar_focused_text = stackbar_focused_text
.unwrap_or(komorebi_themes::CatppuccinValue::Green)
.color32(name.as_theme());
let stackbar_unfocused_text = stackbar_unfocused_text
.unwrap_or(komorebi_themes::CatppuccinValue::Text)
.color32(name.as_theme());
let stackbar_background = stackbar_background
.unwrap_or(komorebi_themes::CatppuccinValue::Base)
.color32(name.as_theme());
(
single_border,
stack_border,
monocle_border,
floating_border,
unfocused_border,
stackbar_focused_text,
stackbar_unfocused_text,
stackbar_background,
)
}
KomorebiTheme::Base16 {
name,
single_border,
stack_border,
monocle_border,
floating_border,
unfocused_border,
stackbar_focused_text,
stackbar_unfocused_text,
stackbar_background,
..
} => {
let single_border = single_border
.unwrap_or(komorebi_themes::Base16Value::Base0D)
.color32(*name);
let stack_border = stack_border
.unwrap_or(komorebi_themes::Base16Value::Base0B)
.color32(*name);
let monocle_border = monocle_border
.unwrap_or(komorebi_themes::Base16Value::Base0F)
.color32(*name);
let unfocused_border = unfocused_border
.unwrap_or(komorebi_themes::Base16Value::Base01)
.color32(*name);
let floating_border = floating_border
.unwrap_or(komorebi_themes::Base16Value::Base09)
.color32(*name);
let stackbar_focused_text = stackbar_focused_text
.unwrap_or(komorebi_themes::Base16Value::Base0B)
.color32(*name);
let stackbar_unfocused_text = stackbar_unfocused_text
.unwrap_or(komorebi_themes::Base16Value::Base05)
.color32(*name);
let stackbar_background = stackbar_background
.unwrap_or(komorebi_themes::Base16Value::Base01)
.color32(*name);
(
single_border,
stack_border,
monocle_border,
floating_border,
unfocused_border,
stackbar_focused_text,
stackbar_unfocused_text,
stackbar_background,
)
}
};
border_manager::FOCUSED.store(u32::from(Colour::from(single_border)), Ordering::SeqCst);
border_manager::MONOCLE
.store(u32::from(Colour::from(monocle_border)), Ordering::SeqCst);
border_manager::STACK.store(u32::from(Colour::from(stack_border)), Ordering::SeqCst);
border_manager::FLOATING
.store(u32::from(Colour::from(floating_border)), Ordering::SeqCst);
border_manager::UNFOCUSED
.store(u32::from(Colour::from(unfocused_border)), Ordering::SeqCst);
STACKBAR_TAB_BACKGROUND_COLOUR.store(
u32::from(Colour::from(stackbar_background)),
Ordering::SeqCst,
);
STACKBAR_FOCUSED_TEXT_COLOUR.store(
u32::from(Colour::from(stackbar_focused_text)),
Ordering::SeqCst,
);
STACKBAR_UNFOCUSED_TEXT_COLOUR.store(
u32::from(Colour::from(stackbar_unfocused_text)),
Ordering::SeqCst,
);
theme_manager::send_notification(*theme);
}
if let Some(path) = &self.app_specific_configuration_path {

View File

@@ -0,0 +1,224 @@
#![deny(clippy::unwrap_used, clippy::expect_used)]
use crate::border_manager;
use crate::stackbar_manager;
use crate::stackbar_manager::STACKBAR_FOCUSED_TEXT_COLOUR;
use crate::stackbar_manager::STACKBAR_TAB_BACKGROUND_COLOUR;
use crate::stackbar_manager::STACKBAR_UNFOCUSED_TEXT_COLOUR;
use crate::Colour;
use crate::KomorebiTheme;
use crossbeam_channel::Receiver;
use crossbeam_channel::Sender;
use crossbeam_utils::atomic::AtomicCell;
use std::ops::Deref;
use std::sync::atomic::Ordering;
use std::sync::OnceLock;
pub struct Notification(KomorebiTheme);
pub static CURRENT_THEME: AtomicCell<Option<KomorebiTheme>> = AtomicCell::new(None);
impl Deref for Notification {
type Target = KomorebiTheme;
fn deref(&self) -> &Self::Target {
&self.0
}
}
static CHANNEL: OnceLock<(Sender<Notification>, Receiver<Notification>)> = OnceLock::new();
pub fn channel() -> &'static (Sender<Notification>, Receiver<Notification>) {
CHANNEL.get_or_init(|| crossbeam_channel::bounded(20))
}
fn event_tx() -> Sender<Notification> {
channel().0.clone()
}
fn event_rx() -> Receiver<Notification> {
channel().1.clone()
}
// Currently this should only be used for async focus updates, such as
// when an animation finishes and we need to focus to set the cursor
// position if the user has mouse follows focus enabled
pub fn send_notification(theme: KomorebiTheme) {
if event_tx().try_send(Notification(theme)).is_err() {
tracing::warn!("channel is full; dropping notification")
}
}
pub fn listen_for_notifications() {
std::thread::spawn(move || loop {
match handle_notifications() {
Ok(()) => {
tracing::warn!("restarting finished thread");
}
Err(error) => {
tracing::warn!("restarting failed thread: {}", error);
}
}
});
}
pub fn handle_notifications() -> color_eyre::Result<()> {
tracing::info!("listening");
let receiver = event_rx();
for notification in receiver {
let theme = &notification.0;
let (
single_border,
stack_border,
monocle_border,
floating_border,
unfocused_border,
stackbar_focused_text,
stackbar_unfocused_text,
stackbar_background,
) = match theme {
KomorebiTheme::Catppuccin {
name,
single_border,
stack_border,
monocle_border,
floating_border,
unfocused_border,
stackbar_focused_text,
stackbar_unfocused_text,
stackbar_background,
..
} => {
let single_border = single_border
.unwrap_or(komorebi_themes::CatppuccinValue::Blue)
.color32(name.as_theme());
let stack_border = stack_border
.unwrap_or(komorebi_themes::CatppuccinValue::Green)
.color32(name.as_theme());
let monocle_border = monocle_border
.unwrap_or(komorebi_themes::CatppuccinValue::Pink)
.color32(name.as_theme());
let floating_border = floating_border
.unwrap_or(komorebi_themes::CatppuccinValue::Yellow)
.color32(name.as_theme());
let unfocused_border = unfocused_border
.unwrap_or(komorebi_themes::CatppuccinValue::Base)
.color32(name.as_theme());
let stackbar_focused_text = stackbar_focused_text
.unwrap_or(komorebi_themes::CatppuccinValue::Green)
.color32(name.as_theme());
let stackbar_unfocused_text = stackbar_unfocused_text
.unwrap_or(komorebi_themes::CatppuccinValue::Text)
.color32(name.as_theme());
let stackbar_background = stackbar_background
.unwrap_or(komorebi_themes::CatppuccinValue::Base)
.color32(name.as_theme());
(
single_border,
stack_border,
monocle_border,
floating_border,
unfocused_border,
stackbar_focused_text,
stackbar_unfocused_text,
stackbar_background,
)
}
KomorebiTheme::Base16 {
name,
single_border,
stack_border,
monocle_border,
floating_border,
unfocused_border,
stackbar_focused_text,
stackbar_unfocused_text,
stackbar_background,
..
} => {
let single_border = single_border
.unwrap_or(komorebi_themes::Base16Value::Base0D)
.color32(*name);
let stack_border = stack_border
.unwrap_or(komorebi_themes::Base16Value::Base0B)
.color32(*name);
let monocle_border = monocle_border
.unwrap_or(komorebi_themes::Base16Value::Base0F)
.color32(*name);
let unfocused_border = unfocused_border
.unwrap_or(komorebi_themes::Base16Value::Base01)
.color32(*name);
let floating_border = floating_border
.unwrap_or(komorebi_themes::Base16Value::Base09)
.color32(*name);
let stackbar_focused_text = stackbar_focused_text
.unwrap_or(komorebi_themes::Base16Value::Base0B)
.color32(*name);
let stackbar_unfocused_text = stackbar_unfocused_text
.unwrap_or(komorebi_themes::Base16Value::Base05)
.color32(*name);
let stackbar_background = stackbar_background
.unwrap_or(komorebi_themes::Base16Value::Base01)
.color32(*name);
(
single_border,
stack_border,
monocle_border,
floating_border,
unfocused_border,
stackbar_focused_text,
stackbar_unfocused_text,
stackbar_background,
)
}
};
border_manager::FOCUSED.store(u32::from(Colour::from(single_border)), Ordering::SeqCst);
border_manager::MONOCLE.store(u32::from(Colour::from(monocle_border)), Ordering::SeqCst);
border_manager::STACK.store(u32::from(Colour::from(stack_border)), Ordering::SeqCst);
border_manager::FLOATING.store(u32::from(Colour::from(floating_border)), Ordering::SeqCst);
border_manager::UNFOCUSED
.store(u32::from(Colour::from(unfocused_border)), Ordering::SeqCst);
STACKBAR_TAB_BACKGROUND_COLOUR.store(
u32::from(Colour::from(stackbar_background)),
Ordering::SeqCst,
);
STACKBAR_FOCUSED_TEXT_COLOUR.store(
u32::from(Colour::from(stackbar_focused_text)),
Ordering::SeqCst,
);
STACKBAR_UNFOCUSED_TEXT_COLOUR.store(
u32::from(Colour::from(stackbar_unfocused_text)),
Ordering::SeqCst,
);
CURRENT_THEME.store(Some(notification.0));
border_manager::send_notification(None);
stackbar_manager::send_notification();
}
Ok(())
}

View File

@@ -1428,6 +1428,7 @@
]
},
"name": {
"description": "Name of the Catppuccin theme (theme previews: https://github.com/catppuccin/catppuccin)",
"type": "string",
"enum": [
"Frappe",
@@ -1474,6 +1475,7 @@
]
},
"name": {
"description": "Name of the Base16 theme (theme previews: https://tinted-theming.github.io/base16-gallery)",
"type": "string",
"enum": [
"3024",

View File

@@ -579,7 +579,7 @@
}
},
"focus_follows_mouse": {
"description": "Determine focus follows mouse implementation (default: None)",
"description": "END OF LIFE FEATURE: Determine focus follows mouse implementation (default: None)",
"oneOf": [
{
"description": "A custom FFM implementation (slightly more CPU-intensive)",
@@ -1052,11 +1052,11 @@
"format": "int32"
},
"custom_layout": {
"description": "Custom Layout (default: None)",
"description": "END OF LIFE FEATURE: Custom Layout (default: None)",
"type": "string"
},
"custom_layout_rules": {
"description": "Layout rules (default: None)",
"description": "END OF LIFE FEATURE: Custom layout rules (default: None)",
"type": "object",
"additionalProperties": {
"type": "string"
@@ -1751,7 +1751,7 @@
]
},
"name": {
"description": "Name of the Catppuccin theme",
"description": "Name of the Catppuccin theme (theme previews: https://github.com/catppuccin/catppuccin)",
"type": "string",
"enum": [
"Frappe",
@@ -2035,7 +2035,7 @@
]
},
"name": {
"description": "Name of the Base16 theme",
"description": "Name of the Base16 theme (theme previews: https://tinted-theming.github.io/base16-gallery)",
"type": "string",
"enum": [
"3024",