glass: blur strength as a config value
shell.conf blur (1 to 30, default 3; Hyprland's default is 8) sets how much Hyprland frosts what is behind the glass, applied the moment shell.conf is saved. Hyprland's blur strength is global (a layer rule can only switch blur on), so the shell sets decoration.blur.size through hyprctl eval, and again on every configreloaded>> event, since a config reload puts Hyprland's own value back. leaving blur out keeps Hyprland's
This commit is contained in:
@@ -30,6 +30,7 @@ The Material You scheme type is Skwd-wall's setting (`matugen.schemeType`).
|
||||
cover_colors = false # true: the open media card and equalizer take the song cover's colours as background
|
||||
transition_ms = 400 # how long a colour change cross-fades; 0 switches instantly
|
||||
glass = 1.0 # surface opacity, 0.05 to 1; below 1 the desktop shows through
|
||||
blur = 3 # Hyprland's blur strength behind the glass, 1 to 30 (Hyprland default 8)
|
||||
```
|
||||
|
||||
## Glass
|
||||
@@ -48,6 +49,8 @@ amane_glass = hl.layer_rule({
|
||||
|
||||
The look of the surfaces (fill, rim, highlight, shadow) lives in `src/surface.rs`.
|
||||
|
||||
`blur` in `shell.conf` sets how much the glass frosts: low values leave the background nearly readable. Hyprland's blur strength is one global setting (a layer rule can only turn blur on), so the shell sets `decoration.blur.size` for everything Hyprland blurs, and sets it again after every Hyprland config reload. Leave `blur` out to keep Hyprland's own value.
|
||||
|
||||
## Layout
|
||||
|
||||
```
|
||||
|
||||
@@ -8,6 +8,11 @@ cover_colors = false
|
||||
# how long a colour change cross-fades, in milliseconds; 0 switches instantly
|
||||
transition_ms = 400
|
||||
|
||||
# how strongly Hyprland blurs what is behind the glass: 1 (barely, nearly readable) to 30;
|
||||
# Hyprland's own default is 8. its blur strength is global, so this also changes the blur
|
||||
# of any other translucent window. leave it out to keep Hyprland's value
|
||||
blur = 3
|
||||
|
||||
# how opaque the shell's surfaces are, 0.05 to 1 (1 = solid). below 1 the desktop shows
|
||||
# through; to frost it, Hyprland has to blur behind the shell (README: Glass)
|
||||
glass = 0.4
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
use std::cell::Cell;
|
||||
use std::io::{BufRead, BufReader};
|
||||
use std::os::unix::net::UnixStream;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
use std::sync::{Mutex, PoisonError};
|
||||
use std::time::Duration;
|
||||
use std::{env, fs, thread};
|
||||
@@ -97,6 +100,9 @@ impl Service for Theme {
|
||||
|
||||
thread::spawn(|| follow("shell.conf"));
|
||||
|
||||
// a hyprland config reload puts its own blur back: ask for ours again
|
||||
thread::spawn(follow_hyprland);
|
||||
|
||||
follow("theme");
|
||||
}
|
||||
}
|
||||
@@ -130,6 +136,59 @@ fn reload() {
|
||||
*last = Some(read);
|
||||
}
|
||||
|
||||
/*
|
||||
* shell.conf `blur`: how strongly Hyprland blurs behind the glass. hyprland's blur
|
||||
* strength is global (a layer rule can only switch blur on), so this sets
|
||||
* decoration.blur.size for everything it blurs. none leaves hyprland's own value
|
||||
*/
|
||||
static BLUR: Mutex<Option<u32>> = Mutex::new(None);
|
||||
|
||||
fn set_blur(size: Option<u32>) {
|
||||
let changed = {
|
||||
let mut blur = BLUR.lock().unwrap_or_else(PoisonError::into_inner);
|
||||
|
||||
let changed = *blur != size;
|
||||
|
||||
*blur = size;
|
||||
|
||||
changed
|
||||
};
|
||||
|
||||
if changed {
|
||||
send_blur();
|
||||
}
|
||||
}
|
||||
|
||||
// on its own thread, so hyprctl never holds up the theme
|
||||
fn send_blur() {
|
||||
let Some(size) = *BLUR.lock().unwrap_or_else(PoisonError::into_inner) else {
|
||||
return;
|
||||
};
|
||||
|
||||
thread::spawn(move || {
|
||||
let lua = format!("hl.config({{ [\"decoration.blur.size\"] = {size} }})");
|
||||
|
||||
let _ = Command::new("hyprctl").arg("eval").arg(lua).output();
|
||||
});
|
||||
}
|
||||
|
||||
// hyprland's event socket says configreloaded>> after every reload, which resets the blur
|
||||
fn follow_hyprland() {
|
||||
let (Some(runtime), Some(instance)) = (env::var_os("XDG_RUNTIME_DIR"), env::var_os("HYPRLAND_INSTANCE_SIGNATURE")) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Ok(events) = UnixStream::connect(PathBuf::from(runtime).join("hypr").join(instance).join(".socket2.sock")) else {
|
||||
return;
|
||||
};
|
||||
|
||||
for line in BufReader::new(events).lines().map_while(Result::ok) {
|
||||
if line.starts_with("configreloaded") {
|
||||
send_blur();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read(name: &str) -> String {
|
||||
fs::read_to_string(config_file(name)).unwrap_or_default()
|
||||
}
|
||||
@@ -180,6 +239,8 @@ fn apply(theme: &str, config: &str, startup: bool) {
|
||||
theme.cover_colors = setting("cover_colors") == Some("true");
|
||||
theme.glass = setting("glass").and_then(|glass| glass.parse::<f32>().ok()).map_or(1.0, |glass| glass.clamp(0.05, 1.0));
|
||||
|
||||
set_blur(setting("blur").and_then(|size| size.parse::<u32>().ok()).map(|size| size.clamp(1, 30)));
|
||||
|
||||
// a change in the middle of a fade starts from the colours on screen now
|
||||
let now = theme.colors.value();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user