diff --git a/jay-config/src/theme.rs b/jay-config/src/theme.rs index 35f1757e..8e15201b 100644 --- a/jay-config/src/theme.rs +++ b/jay-config/src/theme.rs @@ -315,5 +315,11 @@ pub mod sized { /// /// Default: 4 const 02 => BORDER_WIDTH, + /// The height of the bar. + /// + /// Defaults to the TITLE_HEIGHT if not set explicitly. + /// + /// Default: 17 + const 03 => BAR_HEIGHT, } } diff --git a/src/config/handler.rs b/src/config/handler.rs index 8b464863..49223df9 100644 --- a/src/config/handler.rs +++ b/src/config/handler.rs @@ -2302,6 +2302,7 @@ impl ConfigProxyHandler { let sized = match sized { TITLE_HEIGHT => ThemeSized::title_height, BORDER_WIDTH => ThemeSized::border_width, + BAR_HEIGHT => ThemeSized::bar_height, _ => return Err(CphError::UnknownSized(sized.0)), }; Ok(sized) @@ -2309,7 +2310,7 @@ impl ConfigProxyHandler { fn handle_get_size(&self, sized: Resizable) -> Result<(), CphError> { let sized = self.get_sized(sized)?; - let size = sized.field(&self.state.theme).get(); + let size = sized.field(&self.state.theme).val.get(); self.respond(Response::GetSize { size }); Ok(()) } @@ -2322,7 +2323,9 @@ impl ConfigProxyHandler { if size > sized.max() { return Err(CphError::InvalidSize(size, sized)); } - sized.field(&self.state.theme).set(size); + let field = sized.field(&self.state.theme); + field.val.set(size); + field.set.set(true); self.spaces_change(); Ok(()) } diff --git a/src/renderer.rs b/src/renderer.rs index fc6cb4c5..4e9ab16a 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -78,7 +78,7 @@ impl Renderer<'_> { fullscreen = ws.fullscreen.get(); } let theme = &self.state.theme; - let th = theme.sizes.title_height.get(); + let bh = theme.sizes.bar_height(); let srgb_srgb = self.state.color_manager.srgb_gamma22(); let srgb = &srgb_srgb.linear; if let Some(fs) = &fullscreen { @@ -89,7 +89,7 @@ impl Renderer<'_> { let non_exclusive_rect = output.non_exclusive_rect_rel.get(); let (x, mut y) = non_exclusive_rect.translate_inv(x, y); if self.state.show_bar.get() { - let bar_bg = Rect::new_sized(0, 0, non_exclusive_rect.width(), th).unwrap(); + let bar_bg = Rect::new_sized(0, 0, non_exclusive_rect.width(), bh).unwrap(); let bar_bg = self.base.scale_rect(bar_bg); let bar_bg_abs = { let (x, y) = self.base.scale_point(x, y); @@ -166,7 +166,7 @@ impl Renderer<'_> { self.render_surface(&data.surface, rect.x1(), rect.y1(), Some(&bounds)); } } - y += th + 1; + y += bh + 1; } if let Some(ws) = output.workspace.get() { self.render_workspace(&ws, x, y); @@ -196,7 +196,7 @@ impl Renderer<'_> { && ws.render_highlight.get() > 0 { let color = self.state.theme.colors.highlight.get(); - let bounds = ws.position.get().at_point(x, y + th + 1); + let bounds = ws.position.get().at_point(x, y + bh + 1); self.base.ops.push(GfxApiOpt::Sync); self.base.fill_boxes(&[bounds], &color, srgb); } diff --git a/src/state.rs b/src/state.rs index 21e61e93..1c1d30ee 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1524,7 +1524,7 @@ impl State { if !self.show_bar.get() { return 0; } - (self.theme.sizes.title_height.get() - 2).max(0) + (self.theme.sizes.bar_height() - 2).max(0) } pub fn color_management_available(&self) -> bool { diff --git a/src/theme.rs b/src/theme.rs index 787bc73f..78be8640 100644 --- a/src/theme.rs +++ b/src/theme.rs @@ -354,11 +354,22 @@ colors! { highlight = (0x9d, 0x28, 0xc6, 0x7f), } +pub struct ThemeSize { + pub val: Cell, + pub set: Cell, +} + +impl ThemeSize { + pub fn get(&self) -> i32 { + self.val.get() + } +} + macro_rules! sizes { ($($name:ident = ($min:expr, $max:expr, $def:expr),)*) => { pub struct ThemeSizes { $( - pub $name: Cell, + pub $name: ThemeSize, )* } @@ -387,7 +398,7 @@ macro_rules! sizes { } } - pub fn field(self, theme: &Theme) -> &Cell { + pub fn field(self, theme: &Theme) -> &ThemeSize { let sizes = &theme.sizes; match self { $( @@ -409,7 +420,8 @@ macro_rules! sizes { pub fn reset(&self) { let default = Self::default(); $( - self.$name.set(default.$name.get()); + self.$name.val.set(default.$name.val.get()); + self.$name.set.set(false); )* } } @@ -418,7 +430,10 @@ macro_rules! sizes { fn default() -> Self { Self { $( - $name: Cell::new($def), + $name: ThemeSize { + val: Cell::new($def), + set: Cell::new(false), + }, )* } } @@ -426,8 +441,19 @@ macro_rules! sizes { } } +impl ThemeSizes { + pub fn bar_height(&self) -> i32 { + if self.bar_height.set.get() { + self.bar_height.val.get() + } else { + self.title_height.val.get() + } + } +} + sizes! { title_height = (0, 1000, 17), + bar_height = (0, 1000, 17), border_width = (0, 1000, 4), } diff --git a/src/tree/output.rs b/src/tree/output.rs index 1df18b71..51f284ef 100644 --- a/src/tree/output.rs +++ b/src/tree/output.rs @@ -516,16 +516,16 @@ impl OutputNode { }; let font = self.state.theme.font.get(); let theme = &self.state.theme; - let th = theme.sizes.title_height.get(); + let bh = theme.sizes.bar_height(); let scale = self.global.persistent.scale.get(); let scale = if scale != 1 { Some(scale.to_f64()) } else { None }; - let mut texture_height = th; + let mut texture_height = bh; if let Some(scale) = scale { - texture_height = (th as f64 * scale).round() as _; + texture_height = (bh as f64 * scale).round() as _; } let active_id = self.workspace.get().map(|w| w.id); for ws in self.workspaces.iter() { @@ -577,7 +577,7 @@ impl OutputNode { } let mut pos = 0; let theme = &self.state.theme; - let th = theme.sizes.title_height.get(); + let bh = theme.sizes.bar_height(); let scale = self.global.persistent.scale.get(); let scale = if scale != 1 { Some(scale.to_f64()) @@ -587,9 +587,9 @@ impl OutputNode { let active_id = self.workspace.get().map(|w| w.id); let non_exclusive_rect = self.non_exclusive_rect.get(); let output_width = non_exclusive_rect.width(); - rd.underline = Rect::new_sized(0, th, output_width, 1).unwrap(); + rd.underline = Rect::new_sized(0, bh, output_width, 1).unwrap(); for ws in self.workspaces.iter() { - let mut title_width = th; + let mut title_width = bh; let title = &*ws.title_texture.borrow(); if let Some(title) = title { if let Err(e) = title.flip() { @@ -616,7 +616,7 @@ impl OutputNode { }); } } - let rect = Rect::new_sized(pos, 0, title_width, th).unwrap(); + let rect = Rect::new_sized(pos, 0, title_width, bh).unwrap(); if Some(ws.id) == active_id { rd.active_workspace = Some(OutputWorkspaceRenderData { rect, @@ -652,7 +652,7 @@ impl OutputNode { non_exclusive_rect.x1(), non_exclusive_rect.y1(), non_exclusive_rect.width(), - th + 1, + bh + 1, ) .unwrap(); if self.title_visible.get() { @@ -786,7 +786,7 @@ impl OutputNode { pub fn update_rects(self: &Rc) { let rect = self.global.pos.get(); - let th = self.state.theme.sizes.title_height.get(); + let bh = self.state.theme.sizes.bar_height(); let exclusive = self.exclusive_zones.get(); let y1 = rect.y1() + exclusive.top; let x2 = rect.x2() - exclusive.right; @@ -804,7 +804,7 @@ impl OutputNode { )); let mut y1 = y1; if self.state.show_bar.get() { - y1 += th + 1; + y1 += bh + 1; } let height = (y2 - y1).max(0); self.workspace_rect @@ -1136,7 +1136,7 @@ impl OutputNode { self.pointer_down.set(s, (x, y)); } let (x, y) = self.non_exclusive_rect_rel.get().translate(x, y); - if y >= self.state.theme.sizes.title_height.get() { + if y >= self.state.theme.sizes.bar_height() { return; } let ws = 'ws: { @@ -1266,15 +1266,15 @@ impl OutputNode { return None; } let show_bar = self.state.show_bar.get(); - let th = self.state.theme.sizes.title_height.get(); - if show_bar && y_abs < rect.y1() + th + 1 { + let bh = self.state.theme.sizes.bar_height(); + if show_bar && y_abs < rect.y1() + bh + 1 { let rd = &*self.render_data.borrow(); let (x, _) = rect.translate(x_abs, y_abs); let mut last_x2 = 0; for t in &rd.titles { if x < t.x2 { return Some(TileDragDestination { - highlight: Rect::new_sized(rect.x1() + t.x1, rect.y1(), t.x2 - t.x1, th)?, + highlight: Rect::new_sized(rect.x1() + t.x1, rect.y1(), t.x2 - t.x1, bh)?, ty: TddType::MoveToWorkspace { workspace: t.ws.clone(), }, @@ -1287,7 +1287,7 @@ impl OutputNode { rect.x1() + last_x2, rect.y1(), rect.x2() - last_x2, - th, + bh, )?, ty: TddType::MoveToNewWorkspace { output: self.clone(), @@ -1295,7 +1295,7 @@ impl OutputNode { }); } let bar_height = match show_bar { - true => th + 1, + true => bh + 1, false => 0, }; let rect = Rect::new(rect.x1(), rect.y1() + bar_height, rect.x2(), rect.y2())?; @@ -1324,8 +1324,8 @@ impl OutputNode { if !rect.contains(x_abs, y_abs) { return None; } - let th = self.state.theme.sizes.title_height.get(); - if y_abs - rect.y1() > th + 1 { + let bh = self.state.theme.sizes.bar_height(); + if y_abs - rect.y1() > bh + 1 { return None; } if self.state.workspace_display_order.get() == WorkspaceDisplayOrder::Sorted { @@ -1333,7 +1333,7 @@ impl OutputNode { return None; } return Some(WorkspaceDragDestination { - highlight: Rect::new_sized(rect.x1(), rect.y1(), rect.width(), th)?, + highlight: Rect::new_sized(rect.x1(), rect.y1(), rect.width(), bh)?, output: self.clone(), before: None, }); @@ -1357,7 +1357,7 @@ impl OutputNode { rect.x1() + prev_center, rect.y1(), center - prev_center, - th, + bh, )?, output: self.clone(), before: Some(t.ws.clone()), @@ -1375,7 +1375,7 @@ impl OutputNode { rect.x1() + prev_center, rect.y1(), rect.x2() - prev_center, - th, + bh, )?, output: self.clone(), before: None, @@ -1383,7 +1383,7 @@ impl OutputNode { } pub fn update_tray_positions(self: &Rc) { - let th = self.state.theme.sizes.title_height.get(); + let bh = self.state.theme.sizes.bar_height(); let rect = self.non_exclusive_rect.get(); let output_width = rect.width(); let mut right = output_width; @@ -1394,7 +1394,7 @@ impl OutputNode { continue; } have_any = true; - right -= th; + right -= bh; let rel_pos = Rect::new_sized(right, 1, icon_size, icon_size).unwrap(); let abs_pos = rel_pos.move_(rect.x1(), rect.y1()); item.set_position(abs_pos, rel_pos); @@ -1406,7 +1406,7 @@ impl OutputNode { if prev_right != right { { let min = prev_right.min(right); - let rect = Rect::new_sized(rect.x1() + min, 0, output_width, th).unwrap(); + let rect = Rect::new_sized(rect.x1() + min, 0, output_width, bh).unwrap(); self.state.damage(rect); } self.schedule_update_render_data(); @@ -1581,7 +1581,7 @@ impl Node for OutputNode { return FindTreeResult::AcceptsInput; } let bar_height = match self.state.show_bar.get() { - true => self.state.theme.sizes.title_height.get() + 1, + true => self.state.theme.sizes.bar_height() + 1, false => 0, }; if usecase == FindTreeUsecase::SelectWorkspace { diff --git a/toml-config/src/config.rs b/toml-config/src/config.rs index 9aaca933..f0e88a2e 100644 --- a/toml-config/src/config.rs +++ b/toml-config/src/config.rs @@ -195,6 +195,7 @@ pub struct Theme { pub highlight_color: Option, pub border_width: Option, pub title_height: Option, + pub bar_height: Option, pub font: Option, } diff --git a/toml-config/src/config/parsers/theme.rs b/toml-config/src/config/parsers/theme.rs index bc971520..76efa092 100644 --- a/toml-config/src/config/parsers/theme.rs +++ b/toml-config/src/config/parsers/theme.rs @@ -58,6 +58,7 @@ impl Parser for ThemeParser<'_> { highlight_color, border_width, title_height, + bar_height, font, ), ) = ext.extract(( @@ -81,6 +82,7 @@ impl Parser for ThemeParser<'_> { opt(val("highlight-color")), recover(opt(s32("border-width"))), recover(opt(s32("title-height"))), + recover(opt(s32("bar-height"))), recover(opt(str("font"))), ), ))?; @@ -116,6 +118,7 @@ impl Parser for ThemeParser<'_> { highlight_color: color!(highlight_color), border_width: border_width.despan(), title_height: title_height.despan(), + bar_height: bar_height.despan(), font: font.map(|f| f.value.to_string()), }) } diff --git a/toml-config/src/lib.rs b/toml-config/src/lib.rs index cec684db..06be7941 100644 --- a/toml-config/src/lib.rs +++ b/toml-config/src/lib.rs @@ -893,6 +893,7 @@ 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); } diff --git a/toml-spec/spec/spec.generated.json b/toml-spec/spec/spec.generated.json index 174b9f84..d73d8555 100644 --- a/toml-spec/spec/spec.generated.json +++ b/toml-spec/spec/spec.generated.json @@ -1907,6 +1907,11 @@ "description": "The height of tabs.", "minimum": 0.0 }, + "bar-height": { + "type": "integer", + "description": "The height of the bar. Defaults to the title-height if not set.", + "minimum": 0.0 + }, "font": { "type": "string", "description": "The name of the font to use." diff --git a/toml-spec/spec/spec.generated.md b/toml-spec/spec/spec.generated.md index 4f6893ea..1e8e646a 100644 --- a/toml-spec/spec/spec.generated.md +++ b/toml-spec/spec/spec.generated.md @@ -4235,6 +4235,16 @@ The table has the following fields: The numbers should be greater than or equal to 0. +- `bar-height` (optional): + + The height of the bar. Defaults to the title-height if not set. + + The value of this field should be a number. + + The numbers should be integers. + + The numbers should be greater than or equal to 0. + - `font` (optional): The name of the font to use. diff --git a/toml-spec/spec/spec.yaml b/toml-spec/spec/spec.yaml index b9239cca..46d2f3f0 100644 --- a/toml-spec/spec/spec.yaml +++ b/toml-spec/spec/spec.yaml @@ -2123,6 +2123,12 @@ Theme: minimum: 0 required: false description: The height of tabs. + bar-height: + kind: number + integer_only: true + minimum: 0 + required: false + description: The height of the bar. Defaults to the title-height if not set. font: kind: string required: false