From 035e2972de324b010ac345f0ae3b25fa7dafe337 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Wed, 17 Sep 2025 18:37:13 +0200 Subject: [PATCH] theme: add title-font and bar-font settings --- jay-config/src/_private/client.rs | 8 ++++++++ jay-config/src/_private/ipc.rs | 6 ++++++ jay-config/src/theme.rs | 20 +++++++++++++++++++- src/config/handler.rs | 24 ++++++++++++++++++++---- src/theme.rs | 14 ++++++++++++++ src/tree/container.rs | 2 +- src/tree/float.rs | 2 +- src/tree/output.rs | 2 +- toml-config/src/config.rs | 2 ++ toml-config/src/config/parsers/theme.rs | 6 ++++++ toml-config/src/lib.rs | 13 ++++++++++--- toml-spec/spec/spec.generated.json | 8 ++++++++ toml-spec/spec/spec.generated.md | 12 ++++++++++++ toml-spec/spec/spec.yaml | 8 ++++++++ 14 files changed, 116 insertions(+), 11 deletions(-) diff --git a/jay-config/src/_private/client.rs b/jay-config/src/_private/client.rs index f7eed6c0..99e28791 100644 --- a/jay-config/src/_private/client.rs +++ b/jay-config/src/_private/client.rs @@ -650,6 +650,14 @@ impl ConfigClient { self.send(&ClientMessage::SetFont { font }); } + pub fn set_bar_font(&self, font: &str) { + self.send(&ClientMessage::SetBarFont { font }); + } + + pub fn set_title_font(&self, font: &str) { + self.send(&ClientMessage::SetTitleFont { font }); + } + pub fn get_font(&self) -> String { let res = self.send_with_response(&ClientMessage::GetFont); get_response!(res, String::new(), GetFont { font }); diff --git a/jay-config/src/_private/ipc.rs b/jay-config/src/_private/ipc.rs index aabd1343..2a66bd84 100644 --- a/jay-config/src/_private/ipc.rs +++ b/jay-config/src/_private/ipc.rs @@ -768,6 +768,12 @@ pub enum ClientMessage<'a> { connector: Connector, blend_space: BlendSpace, }, + SetBarFont { + font: &'a str, + }, + SetTitleFont { + font: &'a str, + }, } #[derive(Serialize, Deserialize, Debug)] diff --git a/jay-config/src/theme.rs b/jay-config/src/theme.rs index 8e15201b..5618b519 100644 --- a/jay-config/src/theme.rs +++ b/jay-config/src/theme.rs @@ -145,6 +145,8 @@ pub fn get_font() -> String { /// /// Default: `monospace 8`. /// +/// See also [`set_bar_font`] and [`set_title_font`]. +/// /// The font name should be specified in [pango][pango] syntax. /// /// [pango]: https://docs.gtk.org/Pango/type_func.FontDescription.from_string.html @@ -152,7 +154,23 @@ pub fn set_font(font: &str) { get!().set_font(font) } -/// Resets the font to the default. +/// Sets the font used by the bar. +/// +/// If this function is not called, the font set by [`set_font`] is used. See that +/// function for more details. +pub fn set_bar_font(font: &str) { + get!().set_bar_font(font) +} + +/// Sets the font used by window titles. +/// +/// If this function is not called, the font set by [`set_font`] is used. See that +/// function for more details. +pub fn set_title_font(font: &str) { + get!().set_title_font(font) +} + +/// Resets the fonts to the defaults. /// /// Currently the default is `monospace 8`. pub fn reset_font() { diff --git a/src/config/handler.rs b/src/config/handler.rs index 49223df9..e839723a 100644 --- a/src/config/handler.rs +++ b/src/config/handler.rs @@ -2341,16 +2341,30 @@ impl ConfigProxyHandler { } fn handle_reset_font(&self) { - self.state - .theme - .font - .set(self.state.theme.default_font.clone()); + let theme = &self.state.theme; + theme.font.set(self.state.theme.default_font.clone()); + theme.bar_font.set(None); + theme.title_font.set(None); } fn handle_set_font(&self, font: &str) { self.state.theme.font.set(Arc::new(font.to_string())); } + fn handle_set_bar_font(&self, font: &str) { + self.state + .theme + .bar_font + .set(Some(Arc::new(font.to_string()))); + } + + fn handle_set_title_font(&self, font: &str) { + self.state + .theme + .title_font + .set(Some(Arc::new(font.to_string()))); + } + fn handle_get_font(&self) { let font = self.state.theme.font.get().to_string(); self.respond(Response::GetFont { font }); @@ -3143,6 +3157,8 @@ impl ConfigProxyHandler { } => self .handle_connector_set_blend_space(connector, blend_space) .wrn("connector_set_blend_space")?, + ClientMessage::SetBarFont { font } => self.handle_set_bar_font(font), + ClientMessage::SetTitleFont { font } => self.handle_set_title_font(font), } Ok(()) } diff --git a/src/theme.rs b/src/theme.rs index 78be8640..9b4c5e80 100644 --- a/src/theme.rs +++ b/src/theme.rs @@ -463,6 +463,8 @@ pub struct Theme { pub colors: ThemeColors, pub sizes: ThemeSizes, pub font: CloneCell>, + pub bar_font: CloneCell>>, + pub title_font: CloneCell>>, pub default_font: Arc, } @@ -473,7 +475,19 @@ impl Default for Theme { colors: Default::default(), sizes: Default::default(), font: CloneCell::new(default_font.clone()), + bar_font: Default::default(), + title_font: Default::default(), default_font, } } } + +impl Theme { + pub fn title_font(&self) -> Arc { + self.title_font.get().unwrap_or_else(|| self.font.get()) + } + + pub fn bar_font(&self) -> Arc { + self.bar_font.get().unwrap_or_else(|| self.font.get()) + } +} diff --git a/src/tree/container.rs b/src/tree/container.rs index 73576cd1..f3c34548 100644 --- a/src/tree/container.rs +++ b/src/tree/container.rs @@ -707,7 +707,7 @@ impl ContainerNode { }; let theme = &self.state.theme; let th = theme.sizes.title_height.get(); - let font = theme.font.get(); + let font = theme.title_font(); let last_active = self.focus_history.last().map(|v| v.node.node_id()); let have_active = self.children.iter().any(|c| c.active.get()); let scales = self.state.scales.lock(); diff --git a/src/tree/float.rs b/src/tree/float.rs index 649f7934..66d5956c 100644 --- a/src/tree/float.rs +++ b/src/tree/float.rs @@ -205,7 +205,7 @@ impl FloatNode { true => theme.colors.focused_title_text.get(), false => theme.colors.unfocused_title_text.get(), }; - let font = theme.font.get(); + let font = theme.title_font(); let title = self.title.borrow_mut(); let ctx = match self.state.render_ctx.get() { Some(c) => c, diff --git a/src/tree/output.rs b/src/tree/output.rs index 51f284ef..d5d298e8 100644 --- a/src/tree/output.rs +++ b/src/tree/output.rs @@ -514,7 +514,7 @@ impl OutputNode { let Some(ctx) = self.state.render_ctx.get() else { return on_completed.event(); }; - let font = self.state.theme.font.get(); + let font = self.state.theme.bar_font(); let theme = &self.state.theme; let bh = theme.sizes.bar_height(); let scale = self.global.persistent.scale.get(); diff --git a/toml-config/src/config.rs b/toml-config/src/config.rs index f0e88a2e..d8692dbf 100644 --- a/toml-config/src/config.rs +++ b/toml-config/src/config.rs @@ -197,6 +197,8 @@ pub struct Theme { pub title_height: Option, pub bar_height: Option, pub font: Option, + pub title_font: Option, + pub bar_font: Option, } #[derive(Debug, Clone)] diff --git a/toml-config/src/config/parsers/theme.rs b/toml-config/src/config/parsers/theme.rs index 76efa092..b0016b99 100644 --- a/toml-config/src/config/parsers/theme.rs +++ b/toml-config/src/config/parsers/theme.rs @@ -60,7 +60,9 @@ impl Parser for ThemeParser<'_> { title_height, bar_height, font, + title_font, ), + (bar_font,), ) = ext.extract(( ( opt(val("attention-requested-bg-color")), @@ -84,7 +86,9 @@ impl Parser for ThemeParser<'_> { recover(opt(s32("title-height"))), recover(opt(s32("bar-height"))), recover(opt(str("font"))), + recover(opt(str("title-font"))), ), + (recover(opt(str("bar-font"))),), ))?; macro_rules! color { ($e:expr) => { @@ -120,6 +124,8 @@ impl Parser for ThemeParser<'_> { title_height: title_height.despan(), bar_height: bar_height.despan(), font: font.map(|f| f.value.to_string()), + title_font: title_font.map(|f| f.value.to_string()), + bar_font: bar_font.map(|f| f.value.to_string()), }) } } diff --git a/toml-config/src/lib.rs b/toml-config/src/lib.rs index 06be7941..52f9b70a 100644 --- a/toml-config/src/lib.rs +++ b/toml-config/src/lib.rs @@ -41,7 +41,7 @@ use { set_show_float_pin_icon, set_ui_drag_enabled, set_ui_drag_threshold, status::{set_i3bar_separator, set_status, set_status_command, unset_status_command}, switch_to_vt, - theme::{reset_colors, reset_font, reset_sizes, set_font}, + theme::{reset_colors, reset_font, reset_sizes, set_bar_font, set_font, set_title_font}, toggle_float_above_fullscreen, toggle_show_bar, video::{ ColorSpace, Connector, DrmDevice, Eotf, connectors, drm_devices, @@ -894,9 +894,16 @@ impl State { size!(BORDER_WIDTH, border_width); size!(TITLE_HEIGHT, title_height); size!(BAR_HEIGHT, bar_height); - if let Some(font) = &theme.font { - set_font(font); + macro_rules! font { + ($fun:ident, $field:ident) => { + if let Some(font) = &theme.$field { + $fun(font); + } + }; } + font!(set_font, font); + font!(set_title_font, title_font); + font!(set_bar_font, bar_font); } fn handle_switch_device(self: &Rc, dev: InputDevice, actions: &Rc) { diff --git a/toml-spec/spec/spec.generated.json b/toml-spec/spec/spec.generated.json index d73d8555..7c5a04e2 100644 --- a/toml-spec/spec/spec.generated.json +++ b/toml-spec/spec/spec.generated.json @@ -1915,6 +1915,14 @@ "font": { "type": "string", "description": "The name of the font to use." + }, + "title-font": { + "type": "string", + "description": "The name of the font to use in window titles. Defaults to `font` if not set." + }, + "bar-font": { + "type": "string", + "description": "The name of the font to use in the bar. Defaults to `font` if not set." } }, "required": [] diff --git a/toml-spec/spec/spec.generated.md b/toml-spec/spec/spec.generated.md index 1e8e646a..3b265480 100644 --- a/toml-spec/spec/spec.generated.md +++ b/toml-spec/spec/spec.generated.md @@ -4251,6 +4251,18 @@ The table has the following fields: The value of this field should be a string. +- `title-font` (optional): + + The name of the font to use in window titles. Defaults to `font` if not set. + + The value of this field should be a string. + +- `bar-font` (optional): + + The name of the font to use in the bar. Defaults to `font` if not set. + + The value of this field should be a string. + ### `TileState` diff --git a/toml-spec/spec/spec.yaml b/toml-spec/spec/spec.yaml index 46d2f3f0..7f56000a 100644 --- a/toml-spec/spec/spec.yaml +++ b/toml-spec/spec/spec.yaml @@ -2133,6 +2133,14 @@ Theme: kind: string required: false description: The name of the font to use. + title-font: + kind: string + required: false + description: The name of the font to use in window titles. Defaults to `font` if not set. + bar-font: + kind: string + required: false + description: The name of the font to use in the bar. Defaults to `font` if not set. Config: