diff options
| author | MaxVerevkin <maxxverrr@gmail.com> | 2023-04-17 12:26:43 +0300 |
|---|---|---|
| committer | MaxVerevkin <maxxverrr@gmail.com> | 2023-04-17 12:26:43 +0300 |
| commit | d3b488c95817c75ad6ac892e9826da8d9dd189b3 (patch) | |
| tree | ae7c6b93c89e8bc574446de2e6f4bea349b3cc63 | |
| parent | eed0b89aafaee8146688c4ca05146986bbd4dc37 (diff) | |
| download | i3bar-mango-d3b488c95817c75ad6ac892e9826da8d9dd189b3.tar.gz | |
refactor cache management
| -rw-r--r-- | Cargo.lock | 1 | ||||
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | src/bar.rs | 114 | ||||
| -rw-r--r-- | src/blocks_cache.rs | 106 | ||||
| -rw-r--r-- | src/main.rs | 1 | ||||
| -rw-r--r-- | src/shared_state.rs | 5 | ||||
| -rw-r--r-- | src/state.rs | 18 | ||||
| -rw-r--r-- | src/text.rs | 19 |
8 files changed, 145 insertions, 120 deletions
@@ -243,6 +243,7 @@ dependencies = [ "anyhow", "memchr", "nix", + "once_cell", "pangocairo", "serde", "serde_json", @@ -21,6 +21,7 @@ nix = { version = "0.26", default-features = false, features = ["fs", "poll"] } wayrs-client = "0.8" wayrs-utils = { version = "0.4.0-beta.5", features = ["cursor", "shm_alloc", "seats"] } wayrs-protocols = { version = "0.8", features = ["wlr-layer-shell-unstable-v1", "viewporter", "fractional-scale-v1"] } +once_cell = "1.17.1" [profile.release] lto = "fat" @@ -4,14 +4,15 @@ use wayrs_client::connection::Connection; use wayrs_client::proxy::Proxy; use wayrs_utils::shm_alloc::BufferSpec; +use crate::blocks_cache::ComputedBlock; use crate::button_manager::ButtonManager; use crate::color::Color; use crate::config::{Config, Position}; -use crate::i3bar_protocol::{self, Block, MinWidth}; +use crate::i3bar_protocol; use crate::pointer_btn::PointerBtn; use crate::protocol::*; use crate::shared_state::SharedState; -use crate::state::{ComputedBlock, State}; +use crate::state::State; use crate::text::{self, ComputedText, RenderOptions}; use crate::wm_info_provider::WmInfo; @@ -151,7 +152,7 @@ impl Bar { } else { continue; }; - let comp = compute_tag_label(&tag.name, &ss.config, &cairo_ctx); + let comp = compute_tag_label(&tag.name, &ss.config); self.tags_btns .push(offset_left, comp.width, tag.name.clone()); offset_left += comp.width; @@ -201,7 +202,6 @@ impl Bar { align: Default::default(), markup: false, }, - &cairo_ctx, ) }); text.render( @@ -224,8 +224,7 @@ impl Bar { render_blocks( &cairo_ctx, &ss.config, - &ss.blocks, - &mut ss.blocks_cache, + ss.blocks_cache.get_computed(), &mut self.blocks_btns, offset_left, width_f, @@ -293,98 +292,12 @@ impl Bar { fn render_blocks( context: &cairo::Context, config: &Config, - blocks: &[Block], - blocks_cache: &mut Vec<ComputedBlock>, + blocks: &[ComputedBlock], buttons: &mut ButtonManager<(Option<String>, Option<String>)>, offset_left: f64, full_width: f64, full_height: f64, ) { - let comp_min_width = |block: &Block| { - let markup = block.markup.as_deref() == Some("pango"); - match &block.min_width { - Some(MinWidth::Pixels(p)) => Some(*p as f64), - Some(MinWidth::Text(t)) => Some(text::width_of(t, context, markup, &config.font.0)), - None => None, - } - }; - let comp_full = |block: &Block, min_width: Option<f64>| { - let markup = block.markup.as_deref() == Some("pango"); - text::ComputedText::new( - &block.full_text, - text::Attributes { - font: &config.font, - padding_left: 0.0, - padding_right: 0.0, - min_width, - align: block.align.unwrap_or_default(), - markup, - }, - context, - ) - }; - let comp_short = |block: &Block, min_width: Option<f64>| { - let markup = block.markup.as_deref() == Some("pango"); - block.short_text.as_ref().map(|short_text| { - text::ComputedText::new( - short_text, - text::Attributes { - font: &config.font, - padding_left: 0.0, - padding_right: 0.0, - min_width, - align: block.align.unwrap_or_default(), - markup, - }, - context, - ) - }) - }; - - // update cashe - if blocks.len() != blocks_cache.len() { - blocks_cache.clear(); - for block in blocks { - let mw = comp_min_width(block); - blocks_cache.push(ComputedBlock { - block: block.clone(), - full: comp_full(block, mw), - short: comp_short(block, mw), - min_width: mw, - }); - } - } else { - for (block, computed) in blocks.iter().zip(blocks_cache.iter_mut()) { - if block.min_width != computed.block.min_width || block.markup != computed.block.markup - { - let mw = comp_min_width(block); - *computed = ComputedBlock { - block: block.clone(), - full: comp_full(block, mw), - short: comp_short(block, mw), - min_width: mw, - }; - } else { - if block.full_text != computed.block.full_text { - computed.block.full_text = block.full_text.clone(); - computed.full = comp_full(block, computed.min_width); - } - if block.short_text != computed.block.short_text { - computed.block.full_text = block.full_text.clone(); - computed.short = comp_short(block, computed.min_width); - } - computed.block.color = block.color; - computed.block.background = block.background; - computed.block.align = block.align; - computed.block.name = block.name.clone(); - computed.block.instance = block.instance.clone(); - computed.block.separator = block.separator; - computed.block.separator_block_width = block.separator_block_width; - } - } - } - - #[derive(Debug)] struct LogialBlock<'a> { blocks: Vec<&'a ComputedBlock>, delta: f64, @@ -398,10 +311,10 @@ fn render_blocks( let mut s_start = 0; while s_start < blocks.len() { let mut s_end = s_start + 1; - let series_name = &blocks[s_start].name; + let series_name = &blocks[s_start].block.name; while s_end < blocks.len() - && blocks[s_end - 1].separator_block_width == 0 - && &blocks[s_end].name == series_name + && blocks[s_end - 1].block.separator_block_width == 0 + && &blocks[s_end].block.name == series_name { s_end += 1; } @@ -410,11 +323,11 @@ fn render_blocks( blocks: Vec::with_capacity(s_end - s_start), delta: 0.0, switched_to_short: false, - separator: blocks[s_end - 1].separator, - separator_block_width: blocks[s_end - 1].separator_block_width, + separator: blocks[s_end - 1].block.separator, + separator_block_width: blocks[s_end - 1].block.separator_block_width, }; - for comp in &blocks_cache[s_start..s_end] { + for comp in &blocks[s_start..s_end] { blocks_width += comp.full.width; if let Some(short) = &comp.short { series.delta += comp.full.width - short.width; @@ -505,7 +418,7 @@ fn render_blocks( } } -pub fn compute_tag_label(label: &str, config: &Config, context: &cairo::Context) -> ComputedText { +pub fn compute_tag_label(label: &str, config: &Config) -> ComputedText { ComputedText::new( label, text::Attributes { @@ -516,6 +429,5 @@ pub fn compute_tag_label(label: &str, config: &Config, context: &cairo::Context) align: Default::default(), markup: false, }, - context, ) } diff --git a/src/blocks_cache.rs b/src/blocks_cache.rs new file mode 100644 index 0000000..890c13f --- /dev/null +++ b/src/blocks_cache.rs @@ -0,0 +1,106 @@ +use crate::config::Config; +use crate::i3bar_protocol::{Block, MinWidth}; +use crate::text::{self, ComputedText}; + +#[derive(Default)] +pub struct BlocksCache { + computed: Vec<ComputedBlock>, +} + +pub struct ComputedBlock { + pub block: Block, + pub full: ComputedText, + pub short: Option<ComputedText>, + pub min_width: Option<f64>, +} + +impl BlocksCache { + pub fn process_new_blocks(&mut self, config: &Config, blocks: &[Block]) { + let comp_min_width = |block: &Block| { + let markup = block.markup.as_deref() == Some("pango"); + match &block.min_width { + Some(MinWidth::Pixels(p)) => Some(*p as f64), + Some(MinWidth::Text(t)) => Some(text::width_of(t, markup, &config.font.0)), + None => None, + } + }; + let comp_full = |block: &Block, min_width: Option<f64>| { + let markup = block.markup.as_deref() == Some("pango"); + text::ComputedText::new( + &block.full_text, + text::Attributes { + font: &config.font, + padding_left: 0.0, + padding_right: 0.0, + min_width, + align: block.align.unwrap_or_default(), + markup, + }, + ) + }; + let comp_short = |block: &Block, min_width: Option<f64>| { + let markup = block.markup.as_deref() == Some("pango"); + block.short_text.as_ref().map(|short_text| { + text::ComputedText::new( + short_text, + text::Attributes { + font: &config.font, + padding_left: 0.0, + padding_right: 0.0, + min_width, + align: block.align.unwrap_or_default(), + markup, + }, + ) + }) + }; + + // update cashe + if blocks.len() != self.computed.len() { + self.computed.clear(); + for block in blocks { + let mw = comp_min_width(block); + self.computed.push(ComputedBlock { + block: block.clone(), + full: comp_full(block, mw), + short: comp_short(block, mw), + min_width: mw, + }); + } + } else { + for (block, computed) in blocks.iter().zip(self.computed.iter_mut()) { + if block.min_width != computed.block.min_width + || block.markup != computed.block.markup + { + let mw = comp_min_width(block); + *computed = ComputedBlock { + block: block.clone(), + full: comp_full(block, mw), + short: comp_short(block, mw), + min_width: mw, + }; + } else { + if block.full_text != computed.block.full_text { + computed.block.full_text = block.full_text.clone(); + computed.full = comp_full(block, computed.min_width); + } + if block.short_text != computed.block.short_text { + computed.block.full_text = block.full_text.clone(); + computed.short = comp_short(block, computed.min_width); + } + computed.block.color = block.color; + computed.block.background = block.background; + computed.block.align = block.align; + computed.block.name = block.name.clone(); + computed.block.instance = block.instance.clone(); + computed.block.separator = block.separator; + computed.block.separator_block_width = block.separator_block_width; + } + } + } + } + + pub fn get_computed(&self) -> &[ComputedBlock] { + &self.computed + } +} diff --git a/src/main.rs b/src/main.rs index 556d7e1..4ccad5c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,7 @@ extern crate anyhow; mod bar; +mod blocks_cache; mod button_manager; mod color; mod config; diff --git a/src/shared_state.rs b/src/shared_state.rs index 1551f4d..8ec1b60 100644 --- a/src/shared_state.rs +++ b/src/shared_state.rs @@ -1,5 +1,5 @@ use crate::{ - config::Config, i3bar_protocol::Block, state::ComputedBlock, status_cmd::StatusCmd, + blocks_cache::BlocksCache, config::Config, status_cmd::StatusCmd, wm_info_provider::WmInfoProvider, }; @@ -9,7 +9,6 @@ pub struct SharedState { pub shm: ShmAlloc, pub config: Config, pub status_cmd: Option<StatusCmd>, - pub blocks: Vec<Block>, - pub blocks_cache: Vec<ComputedBlock>, + pub blocks_cache: BlocksCache, pub wm_info_provider: Option<Box<dyn WmInfoProvider>>, } diff --git a/src/state.rs b/src/state.rs index 0f8e4a7..86eb45d 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,3 +1,4 @@ +use crate::blocks_cache::BlocksCache; use crate::protocol::*; use crate::wm_info_provider::*; @@ -13,7 +14,7 @@ use wayrs_utils::shm_alloc::ShmAlloc; use crate::{ bar::Bar, config::Config, i3bar_protocol::Block, pointer_btn::PointerBtn, - shared_state::SharedState, status_cmd::StatusCmd, text::ComputedText, wm_info_provider, + shared_state::SharedState, status_cmd::StatusCmd, wm_info_provider, }; pub struct State { @@ -84,8 +85,7 @@ impl State { shm: ShmAlloc::new(wl_shm), config, status_cmd, - blocks: Vec::new(), - blocks_cache: Vec::new(), + blocks_cache: BlocksCache::default(), wm_info_provider: wm_info_provider::bind_wayland(conn, globals, wm_info_cb), }, @@ -105,7 +105,9 @@ impl State { } pub fn set_blocks(&mut self, conn: &mut Connection<Self>, blocks: Vec<Block>) { - self.shared_state.blocks = blocks; + self.shared_state + .blocks_cache + .process_new_blocks(&self.shared_state.config, &blocks); self.draw_all(conn); } @@ -448,14 +450,6 @@ fn wm_info_cb(conn: &mut Connection<State>, state: &mut State, output: WlOutput, bar.request_frame(conn); } -#[derive(Debug)] -pub struct ComputedBlock { - pub block: Block, - pub full: ComputedText, - pub short: Option<ComputedText>, - pub min_width: Option<f64>, -} - #[derive(Debug, Default, Clone, Copy)] pub struct ScrollFrame { stop: bool, diff --git a/src/text.rs b/src/text.rs index 255005a..617a60e 100644 --- a/src/text.rs +++ b/src/text.rs @@ -1,9 +1,19 @@ use crate::color::Color; +use once_cell::sync::Lazy; use pango::FontDescription; use pangocairo::{cairo, pango}; use serde::Deserialize; use std::f64::consts::{FRAC_PI_2, PI, TAU}; +thread_local! { + pub static PANGO_CTX: Lazy<pango::Context> = Lazy::new(|| { + let context = pango::Context::new(); + let fontmap = pangocairo::FontMap::new(); + context.set_font_map(Some(&fontmap)); + context + }); +} + #[derive(Clone, Debug, PartialEq)] pub struct RenderOptions { pub x_offset: f64, @@ -48,10 +58,12 @@ pub struct ComputedText { } impl ComputedText { - pub fn new(text: &str, mut attr: Attributes, context: &cairo::Context) -> Self { + pub fn new(text: &str, mut attr: Attributes) -> Self { let text = text.replace('\n', "\u{23CE}"); - let layout = pangocairo::create_layout(context); + let layout = PANGO_CTX.with(|ctx| pango::Layout::new(ctx)); + layout.set_font_description(Some(attr.font)); + layout.set_font_description(Some(attr.font)); if attr.markup { layout.set_markup(&text); @@ -136,7 +148,7 @@ fn rounded_rectangle( } } -pub fn width_of(text: &str, context: &cairo::Context, markup: bool, font: &FontDescription) -> f64 { +pub fn width_of(text: &str, markup: bool, font: &FontDescription) -> f64 { ComputedText::new( text, Attributes { @@ -147,7 +159,6 @@ pub fn width_of(text: &str, context: &cairo::Context, markup: bool, font: &FontD align: Default::default(), markup, }, - context, ) .width } |
