Add blur to vulkan and opengl render pipelines
This commit is contained in:
parent
6d3bff952e
commit
0701c4e4cf
41 changed files with 1990 additions and 47 deletions
|
|
@ -365,6 +365,34 @@ pub struct WindowMatch {
|
|||
pub content_types: Option<ContentType>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub enum LayerKind {
|
||||
Background,
|
||||
Bottom,
|
||||
Top,
|
||||
Overlay,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone)]
|
||||
pub struct LayerMatch {
|
||||
pub namespace: Option<String>,
|
||||
pub layer: Option<LayerKind>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LayerRule {
|
||||
pub match_: LayerMatch,
|
||||
pub blur: Option<bool>,
|
||||
pub blur_popups: Option<bool>,
|
||||
pub ignore_alpha: Option<f32>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct BlurConfig {
|
||||
pub passes: Option<u8>,
|
||||
pub size: Option<f32>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum DrmDeviceMatch {
|
||||
Any(Vec<DrmDeviceMatch>),
|
||||
|
|
@ -577,6 +605,8 @@ pub struct Config {
|
|||
pub max_action_depth: u64,
|
||||
pub client_rules: Vec<ClientRule>,
|
||||
pub window_rules: Vec<WindowRule>,
|
||||
pub layer_rules: Vec<LayerRule>,
|
||||
pub blur: Option<BlurConfig>,
|
||||
pub pointer_revert_key: Option<KeySym>,
|
||||
pub use_hardware_cursor: Option<bool>,
|
||||
pub show_bar: Option<bool>,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ use {
|
|||
|
||||
pub mod action;
|
||||
mod actions;
|
||||
mod blur;
|
||||
mod capabilities;
|
||||
mod clean_logs_older_than;
|
||||
mod client_match;
|
||||
|
|
@ -32,6 +33,8 @@ mod input;
|
|||
mod input_match;
|
||||
pub mod input_mode;
|
||||
pub mod keymap;
|
||||
mod layer_match;
|
||||
mod layer_rule;
|
||||
mod libei;
|
||||
mod log_level;
|
||||
pub mod mark_id;
|
||||
|
|
|
|||
45
toml-config/src/config/parsers/blur.rs
Normal file
45
toml-config/src/config/parsers/blur.rs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
use {
|
||||
crate::{
|
||||
config::{
|
||||
BlurConfig,
|
||||
context::Context,
|
||||
extractor::{Extractor, ExtractorError, fltorint, int, opt},
|
||||
parser::{DataType, ParseResult, Parser, UnexpectedDataType},
|
||||
},
|
||||
toml::{
|
||||
toml_span::{DespanExt, Span, Spanned},
|
||||
toml_value::Value,
|
||||
},
|
||||
},
|
||||
indexmap::IndexMap,
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum BlurConfigParserError {
|
||||
#[error(transparent)]
|
||||
Expected(#[from] UnexpectedDataType),
|
||||
#[error(transparent)]
|
||||
Extract(#[from] ExtractorError),
|
||||
}
|
||||
|
||||
pub struct BlurConfigParser<'a>(pub &'a Context<'a>);
|
||||
|
||||
impl Parser for BlurConfigParser<'_> {
|
||||
type Value = BlurConfig;
|
||||
type Error = BlurConfigParserError;
|
||||
const EXPECTED: &'static [DataType] = &[DataType::Table];
|
||||
|
||||
fn parse_table(
|
||||
&mut self,
|
||||
span: Span,
|
||||
table: &IndexMap<Spanned<String>, Spanned<Value>>,
|
||||
) -> ParseResult<Self> {
|
||||
let mut ext = Extractor::new(self.0, span, table);
|
||||
let (passes_val, size_val) =
|
||||
ext.extract((opt(int("passes")), opt(fltorint("size"))))?;
|
||||
let passes = passes_val.despan().and_then(|v| u8::try_from(v).ok());
|
||||
let size = size_val.despan().map(|v| v as f32);
|
||||
Ok(BlurConfig { passes, size })
|
||||
}
|
||||
}
|
||||
|
|
@ -23,6 +23,8 @@ use {
|
|||
input::InputsParser,
|
||||
input_mode::InputModesParser,
|
||||
keymap::KeymapParser,
|
||||
blur::BlurConfigParser,
|
||||
layer_rule::LayerRulesParser,
|
||||
libei::LibeiParser,
|
||||
log_level::LogLevelParser,
|
||||
output::OutputsParser,
|
||||
|
|
@ -153,7 +155,9 @@ impl Parser for ConfigParser<'_> {
|
|||
fallback_output_mode_val,
|
||||
clean_logs_older_than_val,
|
||||
mouse_follows_focus,
|
||||
layer_rules_val,
|
||||
),
|
||||
(blur_val,),
|
||||
) = ext.extract((
|
||||
(
|
||||
opt(val("keymap")),
|
||||
|
|
@ -213,7 +217,9 @@ impl Parser for ConfigParser<'_> {
|
|||
opt(val("fallback-output-mode")),
|
||||
opt(val("clean-logs-older-than")),
|
||||
recover(opt(bol("unstable-mouse-follows-focus"))),
|
||||
opt(val("layers")),
|
||||
),
|
||||
(opt(val("blur")),),
|
||||
))?;
|
||||
let mut keymap = None;
|
||||
if let Some(value) = keymap_val {
|
||||
|
|
@ -495,6 +501,20 @@ impl Parser for ConfigParser<'_> {
|
|||
Err(e) => log::warn!("Could not parse the window rules: {}", self.0.error(e)),
|
||||
}
|
||||
}
|
||||
let mut layer_rules = vec![];
|
||||
if let Some(value) = layer_rules_val {
|
||||
match value.parse(&mut LayerRulesParser(self.0)) {
|
||||
Ok(v) => layer_rules = v,
|
||||
Err(e) => log::warn!("Could not parse the layer rules: {}", self.0.error(e)),
|
||||
}
|
||||
}
|
||||
let mut blur = None;
|
||||
if let Some(value) = blur_val {
|
||||
match value.parse(&mut BlurConfigParser(self.0)) {
|
||||
Ok(v) => blur = Some(v),
|
||||
Err(e) => log::warn!("Could not parse the blur config: {}", self.0.error(e)),
|
||||
}
|
||||
}
|
||||
let mut pointer_revert_key = None;
|
||||
if let Some(value) = pointer_revert_key_str {
|
||||
match Keysym::from_str(value.value) {
|
||||
|
|
@ -594,6 +614,8 @@ impl Parser for ConfigParser<'_> {
|
|||
max_action_depth,
|
||||
client_rules,
|
||||
window_rules,
|
||||
layer_rules,
|
||||
blur,
|
||||
pointer_revert_key,
|
||||
use_hardware_cursor: use_hardware_cursor.despan(),
|
||||
show_bar: show_bar.despan(),
|
||||
|
|
|
|||
70
toml-config/src/config/parsers/layer_match.rs
Normal file
70
toml-config/src/config/parsers/layer_match.rs
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
use {
|
||||
crate::{
|
||||
config::{
|
||||
LayerKind, LayerMatch,
|
||||
context::Context,
|
||||
extractor::{Extractor, ExtractorError, opt, str, val},
|
||||
parser::{DataType, ParseResult, Parser, UnexpectedDataType},
|
||||
},
|
||||
toml::{
|
||||
toml_span::{DespanExt, Span, Spanned, SpannedExt},
|
||||
toml_value::Value,
|
||||
},
|
||||
},
|
||||
indexmap::IndexMap,
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum LayerMatchParserError {
|
||||
#[error(transparent)]
|
||||
Expected(#[from] UnexpectedDataType),
|
||||
#[error(transparent)]
|
||||
Extract(#[from] ExtractorError),
|
||||
#[error("Unknown layer `{0}` (expected background, bottom, top, or overlay)")]
|
||||
UnknownLayer(String),
|
||||
}
|
||||
|
||||
pub struct LayerMatchParser<'a>(pub &'a Context<'a>);
|
||||
|
||||
impl Parser for LayerMatchParser<'_> {
|
||||
type Value = LayerMatch;
|
||||
type Error = LayerMatchParserError;
|
||||
const EXPECTED: &'static [DataType] = &[DataType::Table];
|
||||
|
||||
fn parse_table(
|
||||
&mut self,
|
||||
span: Span,
|
||||
table: &IndexMap<Spanned<String>, Spanned<Value>>,
|
||||
) -> ParseResult<Self> {
|
||||
let mut ext = Extractor::new(self.0, span, table);
|
||||
let (namespace, layer_val) = ext.extract((opt(str("namespace")), opt(val("layer"))))?;
|
||||
let mut layer = None;
|
||||
if let Some(value) = layer_val {
|
||||
layer = Some(value.parse(&mut LayerKindParser)?);
|
||||
}
|
||||
Ok(LayerMatch {
|
||||
namespace: namespace.despan_into(),
|
||||
layer,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LayerKindParser;
|
||||
|
||||
impl Parser for LayerKindParser {
|
||||
type Value = LayerKind;
|
||||
type Error = LayerMatchParserError;
|
||||
const EXPECTED: &'static [DataType] = &[DataType::String];
|
||||
|
||||
fn parse_string(&mut self, span: Span, string: &str) -> ParseResult<Self> {
|
||||
let kind = match string {
|
||||
"background" => LayerKind::Background,
|
||||
"bottom" => LayerKind::Bottom,
|
||||
"top" => LayerKind::Top,
|
||||
"overlay" => LayerKind::Overlay,
|
||||
_ => return Err(LayerMatchParserError::UnknownLayer(string.to_string()).spanned(span)),
|
||||
};
|
||||
Ok(kind)
|
||||
}
|
||||
}
|
||||
81
toml-config/src/config/parsers/layer_rule.rs
Normal file
81
toml-config/src/config/parsers/layer_rule.rs
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
use {
|
||||
crate::{
|
||||
config::{
|
||||
LayerMatch, LayerRule,
|
||||
context::Context,
|
||||
extractor::{Extractor, ExtractorError, bol, fltorint, opt, val},
|
||||
parser::{DataType, ParseResult, Parser, UnexpectedDataType},
|
||||
parsers::layer_match::{LayerMatchParser, LayerMatchParserError},
|
||||
},
|
||||
toml::{
|
||||
toml_span::{DespanExt, Span, Spanned},
|
||||
toml_value::Value,
|
||||
},
|
||||
},
|
||||
indexmap::IndexMap,
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum LayerRuleParserError {
|
||||
#[error(transparent)]
|
||||
Expected(#[from] UnexpectedDataType),
|
||||
#[error(transparent)]
|
||||
Extract(#[from] ExtractorError),
|
||||
#[error(transparent)]
|
||||
Match(#[from] LayerMatchParserError),
|
||||
}
|
||||
|
||||
pub struct LayerRuleParser<'a>(pub &'a Context<'a>);
|
||||
|
||||
impl Parser for LayerRuleParser<'_> {
|
||||
type Value = LayerRule;
|
||||
type Error = LayerRuleParserError;
|
||||
const EXPECTED: &'static [DataType] = &[DataType::Table];
|
||||
|
||||
fn parse_table(
|
||||
&mut self,
|
||||
span: Span,
|
||||
table: &IndexMap<Spanned<String>, Spanned<Value>>,
|
||||
) -> ParseResult<Self> {
|
||||
let mut ext = Extractor::new(self.0, span, table);
|
||||
let (match_val, blur, blur_popups, ignore_alpha) = ext.extract((
|
||||
opt(val("match")),
|
||||
opt(bol("blur")),
|
||||
opt(bol("blur-popups")),
|
||||
opt(fltorint("ignore-alpha")),
|
||||
))?;
|
||||
let match_ = match match_val {
|
||||
None => LayerMatch::default(),
|
||||
Some(m) => m.parse_map(&mut LayerMatchParser(self.0))?,
|
||||
};
|
||||
let ignore_alpha = ignore_alpha.map(|s| s.value.clamp(0.0, 1.0) as f32);
|
||||
Ok(LayerRule {
|
||||
match_,
|
||||
blur: blur.despan(),
|
||||
blur_popups: blur_popups.despan(),
|
||||
ignore_alpha,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LayerRulesParser<'a>(pub &'a Context<'a>);
|
||||
|
||||
impl Parser for LayerRulesParser<'_> {
|
||||
type Value = Vec<LayerRule>;
|
||||
type Error = LayerRuleParserError;
|
||||
const EXPECTED: &'static [DataType] = &[DataType::Array];
|
||||
|
||||
fn parse_array(&mut self, _span: Span, array: &[Spanned<Value>]) -> ParseResult<Self> {
|
||||
let mut res = vec![];
|
||||
for el in array {
|
||||
match el.parse(&mut LayerRuleParser(self.0)) {
|
||||
Ok(o) => res.push(o),
|
||||
Err(e) => {
|
||||
log::warn!("Could not parse layer rule: {}", self.0.error(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
|
@ -14,8 +14,9 @@ use {
|
|||
crate::{
|
||||
config::{
|
||||
Action, ClientRule, Config, ConfigConnector, ConfigDrmDevice, ConfigKeymap,
|
||||
ConnectorMatch, DrmDeviceMatch, Exec, Input, InputMatch, Output, OutputMatch,
|
||||
SimpleCommand, Status, Theme, WindowRule, parse_config,
|
||||
BlurConfig, ConnectorMatch, DrmDeviceMatch, Exec, Input, InputMatch, LayerKind,
|
||||
LayerRule, Output,
|
||||
OutputMatch, SimpleCommand, Status, Theme, WindowRule, parse_config,
|
||||
},
|
||||
rules::{MatcherTemp, RuleMapper},
|
||||
shortcuts::ModeState,
|
||||
|
|
@ -37,6 +38,8 @@ use {
|
|||
is_reload,
|
||||
keyboard::Keymap,
|
||||
logging::{clean_logs_older_than, set_log_level},
|
||||
_set_blur_config, _set_layer_rules,
|
||||
_private::{BlurConfigIpc, LayerKindIpc, LayerMatchIpc, LayerRuleIpc},
|
||||
on_devices_enumerated, on_idle, on_unload, quit, reload, set_autotile,
|
||||
set_color_management_enabled, set_corner_radius, set_default_workspace_capture,
|
||||
set_explicit_sync_enabled, set_float_above_fullscreen, set_floating_titles, set_idle,
|
||||
|
|
@ -1470,6 +1473,8 @@ fn load_config(initial_load: bool, auto_reload: bool, persistent: &Rc<Persistent
|
|||
*state.persistent.client_rule_mapper.borrow_mut() = Some(client_rule_mapper);
|
||||
let (window_rules, _) = state.create_rules(&config.window_rules);
|
||||
persistent.window_rules.set(window_rules);
|
||||
push_layer_rules(&config.layer_rules);
|
||||
push_blur_config(config.blur);
|
||||
state.set_status(&config.status);
|
||||
persistent.actions.borrow_mut().clear();
|
||||
for a in config.named_actions {
|
||||
|
|
@ -1719,6 +1724,39 @@ fn load_config(initial_load: bool, auto_reload: bool, persistent: &Rc<Persistent
|
|||
}
|
||||
}
|
||||
|
||||
fn push_blur_config(blur: Option<BlurConfig>) {
|
||||
let default = BlurConfigIpc::default();
|
||||
let cfg = match blur {
|
||||
Some(b) => BlurConfigIpc {
|
||||
passes: b.passes.unwrap_or(default.passes).clamp(1, 8),
|
||||
size: b.size.unwrap_or(default.size).max(0.0),
|
||||
},
|
||||
None => default,
|
||||
};
|
||||
_set_blur_config(cfg);
|
||||
}
|
||||
|
||||
fn push_layer_rules(rules: &[LayerRule]) {
|
||||
let ipc: Vec<LayerRuleIpc> = rules
|
||||
.iter()
|
||||
.map(|r| LayerRuleIpc {
|
||||
match_: LayerMatchIpc {
|
||||
namespace: r.match_.namespace.clone(),
|
||||
layer: r.match_.layer.map(|k| match k {
|
||||
LayerKind::Background => LayerKindIpc::Background,
|
||||
LayerKind::Bottom => LayerKindIpc::Bottom,
|
||||
LayerKind::Top => LayerKindIpc::Top,
|
||||
LayerKind::Overlay => LayerKindIpc::Overlay,
|
||||
}),
|
||||
},
|
||||
blur: r.blur,
|
||||
blur_popups: r.blur_popups,
|
||||
ignore_alpha: r.ignore_alpha,
|
||||
})
|
||||
.collect();
|
||||
_set_layer_rules(ipc);
|
||||
}
|
||||
|
||||
fn create_command(exec: &Exec) -> Command {
|
||||
let mut command = Command::new(&exec.prog);
|
||||
for arg in &exec.args {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue