summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxVerevkin <maxxverrr@gmail.com>2023-04-17 12:26:43 +0300
committerMaxVerevkin <maxxverrr@gmail.com>2023-04-17 12:26:43 +0300
commitd3b488c95817c75ad6ac892e9826da8d9dd189b3 (patch)
treeae7c6b93c89e8bc574446de2e6f4bea349b3cc63 /src
parenteed0b89aafaee8146688c4ca05146986bbd4dc37 (diff)
downloadi3bar-mango-d3b488c95817c75ad6ac892e9826da8d9dd189b3.tar.gz
refactor cache management
Diffstat (limited to 'src')
-rw-r--r--src/bar.rs114
-rw-r--r--src/blocks_cache.rs106
-rw-r--r--src/main.rs1
-rw-r--r--src/shared_state.rs5
-rw-r--r--src/state.rs18
-rw-r--r--src/text.rs19
6 files changed, 143 insertions, 120 deletions
diff --git a/src/bar.rs b/src/bar.rs
index 46b3b72..fe6e305 100644
--- a/src/bar.rs
+++ b/src/bar.rs
@@ -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
}