fix some bugs relating to tab behavior and border rendering
This commit is contained in:
parent
f056727621
commit
206a5fb19e
12 changed files with 240 additions and 172 deletions
|
|
@ -35,6 +35,9 @@ The available color keys in the `[theme]` table are:
|
||||||
`border-color`
|
`border-color`
|
||||||
: Borders between tiled windows
|
: Borders between tiled windows
|
||||||
|
|
||||||
|
`active-border-color`
|
||||||
|
: Borders around active windows
|
||||||
|
|
||||||
`focused-title-bg-color`
|
`focused-title-bg-color`
|
||||||
: Background of the focused window's title
|
: Background of the focused window's title
|
||||||
|
|
||||||
|
|
@ -80,6 +83,7 @@ bg-color = "#1e1e2e"
|
||||||
bar-bg-color = "#181825"
|
bar-bg-color = "#181825"
|
||||||
bar-status-text-color = "#cdd6f4"
|
bar-status-text-color = "#cdd6f4"
|
||||||
border-color = "#313244"
|
border-color = "#313244"
|
||||||
|
active-border-color = "#89b4fa"
|
||||||
focused-title-bg-color = "#89b4fa"
|
focused-title-bg-color = "#89b4fa"
|
||||||
focused-title-text-color = "#1e1e2e"
|
focused-title-text-color = "#1e1e2e"
|
||||||
unfocused-title-bg-color = "#313244"
|
unfocused-title-bg-color = "#313244"
|
||||||
|
|
|
||||||
|
|
@ -269,6 +269,10 @@ pub mod colors {
|
||||||
///
|
///
|
||||||
/// Default: `#3f474a`.
|
/// Default: `#3f474a`.
|
||||||
const 07 => BORDER_COLOR,
|
const 07 => BORDER_COLOR,
|
||||||
|
/// The color of the border around active windows.
|
||||||
|
///
|
||||||
|
/// Default: `#285577`.
|
||||||
|
const 24 => ACTIVE_BORDER_COLOR,
|
||||||
/// The title text color of an unfocused window.
|
/// The title text color of an unfocused window.
|
||||||
///
|
///
|
||||||
/// Default: `#888888`.
|
/// Default: `#888888`.
|
||||||
|
|
|
||||||
|
|
@ -2576,6 +2576,7 @@ impl ConfigProxyHandler {
|
||||||
BAR_BACKGROUND_COLOR => ThemeColor::bar_background,
|
BAR_BACKGROUND_COLOR => ThemeColor::bar_background,
|
||||||
SEPARATOR_COLOR => ThemeColor::separator,
|
SEPARATOR_COLOR => ThemeColor::separator,
|
||||||
BORDER_COLOR => ThemeColor::border,
|
BORDER_COLOR => ThemeColor::border,
|
||||||
|
ACTIVE_BORDER_COLOR => ThemeColor::active_border,
|
||||||
UNFOCUSED_TITLE_TEXT_COLOR => ThemeColor::unfocused_title_text,
|
UNFOCUSED_TITLE_TEXT_COLOR => ThemeColor::unfocused_title_text,
|
||||||
FOCUSED_TITLE_TEXT_COLOR => ThemeColor::focused_title_text,
|
FOCUSED_TITLE_TEXT_COLOR => ThemeColor::focused_title_text,
|
||||||
FOCUSED_INACTIVE_TITLE_TEXT_COLOR => ThemeColor::focused_inactive_title_text,
|
FOCUSED_INACTIVE_TITLE_TEXT_COLOR => ThemeColor::focused_inactive_title_text,
|
||||||
|
|
|
||||||
234
src/renderer.rs
234
src/renderer.rs
|
|
@ -284,8 +284,6 @@ impl Renderer<'_> {
|
||||||
let srgb_srgb = self.state.color_manager.srgb_gamma22();
|
let srgb_srgb = self.state.color_manager.srgb_gamma22();
|
||||||
let srgb = &srgb_srgb.linear;
|
let srgb = &srgb_srgb.linear;
|
||||||
let perceptual = RenderIntent::Perceptual;
|
let perceptual = RenderIntent::Perceptual;
|
||||||
let scalef = self.base.scalef as f32;
|
|
||||||
|
|
||||||
let radius = self.state.theme.sizes.tab_bar_radius.get();
|
let radius = self.state.theme.sizes.tab_bar_radius.get();
|
||||||
let border_width = self.state.theme.sizes.tab_bar_border_width.get();
|
let border_width = self.state.theme.sizes.tab_bar_border_width.get();
|
||||||
let text_padding = self.state.theme.sizes.tab_bar_text_padding.get();
|
let text_padding = self.state.theme.sizes.tab_bar_text_padding.get();
|
||||||
|
|
@ -294,10 +292,10 @@ impl Renderer<'_> {
|
||||||
|
|
||||||
// Vulkan sorts ops: Fill < RoundedFill (by z_order, color) < Tex/RoundedTex (by index).
|
// Vulkan sorts ops: Fill < RoundedFill (by z_order, color) < Tex/RoundedTex (by index).
|
||||||
// We use:
|
// We use:
|
||||||
// FillRect – tiny strip for Vulkan paint regions (hidden)
|
// FillRect - tiny strip for Vulkan paint regions (hidden)
|
||||||
// RoundedFillRect z0 – solid rounded bg
|
// RoundedFillRect z0 - solid rounded bg
|
||||||
// RoundedFillRect z1 – rounded border ring (on top of bg)
|
// RoundedFillRect z1 - rounded border ring (on top of bg)
|
||||||
// RoundedCopyTexture – title text (on top of everything)
|
// RoundedCopyTexture - title text (on top of everything)
|
||||||
for entry in &tab_bar.entries {
|
for entry in &tab_bar.entries {
|
||||||
let (bg_color, border_color, _text_color) = TabBar::entry_colors(self.state, entry);
|
let (bg_color, border_color, _text_color) = TabBar::entry_colors(self.state, entry);
|
||||||
let ex = entry.x.get();
|
let ex = entry.x.get();
|
||||||
|
|
@ -323,7 +321,7 @@ impl Renderer<'_> {
|
||||||
None,
|
None,
|
||||||
srgb,
|
srgb,
|
||||||
perceptual,
|
perceptual,
|
||||||
tab_cr.scaled_by(scalef),
|
self.scale_corner_radius(tab_cr),
|
||||||
0.0,
|
0.0,
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
|
|
@ -336,8 +334,8 @@ impl Renderer<'_> {
|
||||||
None,
|
None,
|
||||||
srgb,
|
srgb,
|
||||||
perceptual,
|
perceptual,
|
||||||
tab_cr.scaled_by(scalef),
|
self.scale_corner_radius(tab_cr),
|
||||||
border_width as f32 * scalef,
|
self.scale_len(border_width),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -386,6 +384,65 @@ impl Renderer<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn scale_len(&self, len: i32) -> f32 {
|
||||||
|
if self.base.scaled {
|
||||||
|
(len as f64 * self.base.scalef).round() as f32
|
||||||
|
} else {
|
||||||
|
len as f32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn scale_corner_radius(&self, cr: CornerRadius) -> CornerRadius {
|
||||||
|
if !self.base.scaled {
|
||||||
|
return cr;
|
||||||
|
}
|
||||||
|
let scale = self.base.scalef as f32;
|
||||||
|
CornerRadius {
|
||||||
|
top_left: (cr.top_left * scale).round(),
|
||||||
|
top_right: (cr.top_right * scale).round(),
|
||||||
|
bottom_right: (cr.bottom_right * scale).round(),
|
||||||
|
bottom_left: (cr.bottom_left * scale).round(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_rounded_frame(
|
||||||
|
&mut self,
|
||||||
|
rect: Rect,
|
||||||
|
color: &Color,
|
||||||
|
corner_radius: CornerRadius,
|
||||||
|
border_width: i32,
|
||||||
|
x: i32,
|
||||||
|
y: i32,
|
||||||
|
) {
|
||||||
|
if border_width <= 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let srgb_srgb = self.state.color_manager.srgb_gamma22();
|
||||||
|
let srgb = &srgb_srgb.linear;
|
||||||
|
let perceptual = RenderIntent::Perceptual;
|
||||||
|
if corner_radius.is_zero() {
|
||||||
|
let bw = border_width;
|
||||||
|
let frame_rects = [
|
||||||
|
Rect::new_sized_saturating(rect.x1(), rect.y1(), bw, rect.height()),
|
||||||
|
Rect::new_sized_saturating(rect.x2() - bw, rect.y1(), bw, rect.height()),
|
||||||
|
Rect::new_sized_saturating(rect.x1(), rect.y1(), rect.width(), bw),
|
||||||
|
Rect::new_sized_saturating(rect.x1(), rect.y2() - bw, rect.width(), bw),
|
||||||
|
];
|
||||||
|
self.base
|
||||||
|
.fill_boxes2(&frame_rects, color, srgb, perceptual, x, y);
|
||||||
|
} else {
|
||||||
|
self.base.fill_rounded_rect(
|
||||||
|
rect.move_(x, y),
|
||||||
|
color,
|
||||||
|
None,
|
||||||
|
srgb,
|
||||||
|
perceptual,
|
||||||
|
self.scale_corner_radius(corner_radius),
|
||||||
|
self.scale_len(border_width),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn render_container_decorations(&mut self, container: &ContainerNode, x: i32, y: i32) {
|
fn render_container_decorations(&mut self, container: &ContainerNode, x: i32, y: i32) {
|
||||||
let srgb_srgb = self.state.color_manager.srgb_gamma22();
|
let srgb_srgb = self.state.color_manager.srgb_gamma22();
|
||||||
let srgb = &srgb_srgb.linear;
|
let srgb = &srgb_srgb.linear;
|
||||||
|
|
@ -409,60 +466,29 @@ impl Renderer<'_> {
|
||||||
}
|
}
|
||||||
let mb = container.mono_body.get();
|
let mb = container.mono_body.get();
|
||||||
if self.state.theme.sizes.gap.get() != 0 {
|
if self.state.theme.sizes.gap.get() != 0 {
|
||||||
let srgb_srgb = self.state.color_manager.srgb_gamma22();
|
|
||||||
let bw = self.state.theme.sizes.border_width.get();
|
let bw = self.state.theme.sizes.border_width.get();
|
||||||
let border_color = self.state.theme.colors.border.get();
|
let border_color = self.state.theme.colors.border.get();
|
||||||
let focused_border_color = self.state.theme.colors.focused_title_background.get();
|
let focused_border_color = self.state.theme.colors.active_border.get();
|
||||||
let c = if child.active.get() {
|
let c = if child.active.get() {
|
||||||
&focused_border_color
|
&focused_border_color
|
||||||
} else {
|
} else {
|
||||||
&border_color
|
&border_color
|
||||||
};
|
};
|
||||||
let full_w = mb.width();
|
|
||||||
let srgb = &srgb_srgb.linear;
|
|
||||||
let perceptual = RenderIntent::Perceptual;
|
|
||||||
if !child.node.node_is_container() {
|
if !child.node.node_is_container() {
|
||||||
let cr = self.state.theme.corner_radius.get();
|
let frame = Rect::new_sized_saturating(
|
||||||
let frame_y = mb.y1();
|
mb.x1() - bw,
|
||||||
let frame_h = mb.height();
|
mb.y1() - bw,
|
||||||
if cr.is_zero() {
|
mb.width() + 2 * bw,
|
||||||
let frame_rects = [
|
mb.height() + 2 * bw,
|
||||||
Rect::new_sized_saturating(mb.x1() - bw, frame_y, bw, frame_h),
|
);
|
||||||
Rect::new_sized_saturating(mb.x2(), frame_y, bw, frame_h),
|
self.render_rounded_frame(
|
||||||
Rect::new_sized_saturating(
|
frame,
|
||||||
mb.x1() - bw,
|
c,
|
||||||
frame_y - bw,
|
self.state.theme.corner_radius.get(),
|
||||||
full_w + 2 * bw,
|
bw,
|
||||||
bw,
|
x,
|
||||||
),
|
y,
|
||||||
Rect::new_sized_saturating(
|
);
|
||||||
mb.x1() - bw,
|
|
||||||
frame_y + frame_h,
|
|
||||||
full_w + 2 * bw,
|
|
||||||
bw,
|
|
||||||
),
|
|
||||||
];
|
|
||||||
self.base
|
|
||||||
.fill_boxes2(&frame_rects, c, srgb, perceptual, x, y);
|
|
||||||
} else {
|
|
||||||
let outer = Rect::new_sized_saturating(
|
|
||||||
mb.x1() - bw,
|
|
||||||
frame_y - bw,
|
|
||||||
full_w + 2 * bw,
|
|
||||||
frame_h + 2 * bw,
|
|
||||||
);
|
|
||||||
let scalef = self.base.scalef as f32;
|
|
||||||
let scaled_cr = cr.scaled_by(scalef);
|
|
||||||
self.base.fill_rounded_rect(
|
|
||||||
outer.move_(x, y),
|
|
||||||
c,
|
|
||||||
None,
|
|
||||||
srgb,
|
|
||||||
perceptual,
|
|
||||||
scaled_cr,
|
|
||||||
bw as f32 * scalef,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let body = mb.move_(x, y);
|
let body = mb.move_(x, y);
|
||||||
|
|
@ -476,9 +502,8 @@ impl Renderer<'_> {
|
||||||
if self.state.theme.sizes.gap.get() != 0 && !child.node.node_is_container() {
|
if self.state.theme.sizes.gap.get() != 0 && !child.node.node_is_container() {
|
||||||
let cr = self.state.theme.corner_radius.get();
|
let cr = self.state.theme.corner_radius.get();
|
||||||
if !cr.is_zero() {
|
if !cr.is_zero() {
|
||||||
let scalef = self.base.scalef as f32;
|
|
||||||
let bw = self.state.theme.sizes.border_width.get();
|
let bw = self.state.theme.sizes.border_width.get();
|
||||||
let inner_cr = cr.expanded_by(-(bw as f32)).scaled_by(scalef);
|
let inner_cr = self.scale_corner_radius(cr.expanded_by(-(bw as f32)));
|
||||||
self.corner_radius = Some(inner_cr);
|
self.corner_radius = Some(inner_cr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -489,14 +514,13 @@ impl Renderer<'_> {
|
||||||
self.corner_radius = None;
|
self.corner_radius = None;
|
||||||
} else {
|
} else {
|
||||||
let gap = self.state.theme.sizes.gap.get();
|
let gap = self.state.theme.sizes.gap.get();
|
||||||
let (srgb_srgb, bw, border_color, focused_border_color) = if gap != 0 {
|
let (bw, border_color, focused_border_color) = if gap != 0 {
|
||||||
let srgb_srgb = self.state.color_manager.srgb_gamma22();
|
|
||||||
let bw = self.state.theme.sizes.border_width.get();
|
let bw = self.state.theme.sizes.border_width.get();
|
||||||
let border_color = self.state.theme.colors.border.get();
|
let border_color = self.state.theme.colors.border.get();
|
||||||
let focused_border_color = self.state.theme.colors.focused_title_background.get();
|
let focused_border_color = self.state.theme.colors.active_border.get();
|
||||||
(Some(srgb_srgb), bw, border_color, focused_border_color)
|
(bw, border_color, focused_border_color)
|
||||||
} else {
|
} else {
|
||||||
(None, 0, Color::SOLID_BLACK, Color::SOLID_BLACK)
|
(0, Color::SOLID_BLACK, Color::SOLID_BLACK)
|
||||||
};
|
};
|
||||||
let cr = self.state.theme.corner_radius.get();
|
let cr = self.state.theme.corner_radius.get();
|
||||||
for child in container.children.iter() {
|
for child in container.children.iter() {
|
||||||
|
|
@ -504,55 +528,20 @@ impl Renderer<'_> {
|
||||||
if body.x1() >= container.width.get() || body.y1() >= container.height.get() {
|
if body.x1() >= container.width.get() || body.y1() >= container.height.get() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if let Some(srgb_srgb) = srgb_srgb {
|
if gap != 0 {
|
||||||
let srgb = &srgb_srgb.linear;
|
|
||||||
let c = if child.border_color_is_focused.get() {
|
let c = if child.border_color_is_focused.get() {
|
||||||
&focused_border_color
|
&focused_border_color
|
||||||
} else {
|
} else {
|
||||||
&border_color
|
&border_color
|
||||||
};
|
};
|
||||||
if !child.node.node_is_container() && gap != 0 {
|
if !child.node.node_is_container() && gap != 0 {
|
||||||
let full_w = body.width();
|
let frame = Rect::new_sized_saturating(
|
||||||
let perceptual = RenderIntent::Perceptual;
|
body.x1() - bw,
|
||||||
let full_h = body.height();
|
body.y1() - bw,
|
||||||
if cr.is_zero() {
|
body.width() + 2 * bw,
|
||||||
let frame_rects = [
|
body.height() + 2 * bw,
|
||||||
Rect::new_sized_saturating(body.x1() - bw, body.y1(), bw, full_h),
|
);
|
||||||
Rect::new_sized_saturating(body.x2(), body.y1(), bw, full_h),
|
self.render_rounded_frame(frame, c, cr, bw, x, y);
|
||||||
Rect::new_sized_saturating(
|
|
||||||
body.x1() - bw,
|
|
||||||
body.y1() - bw,
|
|
||||||
full_w + 2 * bw,
|
|
||||||
bw,
|
|
||||||
),
|
|
||||||
Rect::new_sized_saturating(
|
|
||||||
body.x1() - bw,
|
|
||||||
body.y2(),
|
|
||||||
full_w + 2 * bw,
|
|
||||||
bw,
|
|
||||||
),
|
|
||||||
];
|
|
||||||
self.base
|
|
||||||
.fill_boxes2(&frame_rects, c, srgb, perceptual, x, y);
|
|
||||||
} else {
|
|
||||||
let outer = Rect::new_sized_saturating(
|
|
||||||
body.x1() - bw,
|
|
||||||
body.y1() - bw,
|
|
||||||
full_w + 2 * bw,
|
|
||||||
full_h + 2 * bw,
|
|
||||||
);
|
|
||||||
let scalef = self.base.scalef as f32;
|
|
||||||
let scaled_cr = cr.scaled_by(scalef);
|
|
||||||
self.base.fill_rounded_rect(
|
|
||||||
outer.move_(x, y),
|
|
||||||
c,
|
|
||||||
None,
|
|
||||||
srgb,
|
|
||||||
perceptual,
|
|
||||||
scaled_cr,
|
|
||||||
bw as f32 * scalef,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let content = child.content.get();
|
let content = child.content.get();
|
||||||
|
|
@ -563,8 +552,7 @@ impl Renderer<'_> {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
if !cr.is_zero() && !child.node.node_is_container() && gap != 0 {
|
if !cr.is_zero() && !child.node.node_is_container() && gap != 0 {
|
||||||
let scalef = self.base.scalef as f32;
|
let inner_cr = self.scale_corner_radius(cr.expanded_by(-(bw as f32)));
|
||||||
let inner_cr = cr.expanded_by(-(bw as f32)).scaled_by(scalef);
|
|
||||||
self.corner_radius = Some(inner_cr);
|
self.corner_radius = Some(inner_cr);
|
||||||
}
|
}
|
||||||
let body = body.move_(x, y);
|
let body = body.move_(x, y);
|
||||||
|
|
@ -808,42 +796,18 @@ impl Renderer<'_> {
|
||||||
let theme = &self.state.theme;
|
let theme = &self.state.theme;
|
||||||
let bw = theme.sizes.border_width.get();
|
let bw = theme.sizes.border_width.get();
|
||||||
let bc = if floating.active.get() {
|
let bc = if floating.active.get() {
|
||||||
theme.colors.focused_title_background.get()
|
theme.colors.active_border.get()
|
||||||
} else {
|
} else {
|
||||||
theme.colors.border.get()
|
theme.colors.border.get()
|
||||||
};
|
};
|
||||||
let srgb_srgb = self.state.color_manager.srgb_gamma22();
|
|
||||||
let srgb = &srgb_srgb.linear;
|
|
||||||
let perceptual = RenderIntent::Perceptual;
|
|
||||||
let cr = theme.corner_radius.get();
|
let cr = theme.corner_radius.get();
|
||||||
if cr.is_zero() {
|
let outer = Rect::new_sized_saturating(0, 0, pos.width(), pos.height());
|
||||||
let borders = [
|
self.render_rounded_frame(outer, &bc, cr, bw, x, y);
|
||||||
Rect::new_sized_saturating(x, y, pos.width(), bw),
|
|
||||||
Rect::new_sized_saturating(x, y + bw, bw, pos.height() - bw),
|
|
||||||
Rect::new_sized_saturating(x + pos.width() - bw, y + bw, bw, pos.height() - bw),
|
|
||||||
Rect::new_sized_saturating(x + bw, y + pos.height() - bw, pos.width() - 2 * bw, bw),
|
|
||||||
];
|
|
||||||
self.base.fill_boxes(&borders, &bc, srgb, perceptual);
|
|
||||||
} else {
|
|
||||||
let outer = Rect::new_sized_saturating(x, y, pos.width(), pos.height());
|
|
||||||
let scalef = self.base.scalef as f32;
|
|
||||||
let scaled_cr = cr.scaled_by(scalef);
|
|
||||||
self.base.fill_rounded_rect(
|
|
||||||
outer,
|
|
||||||
&bc,
|
|
||||||
None,
|
|
||||||
srgb,
|
|
||||||
perceptual,
|
|
||||||
scaled_cr,
|
|
||||||
bw as f32 * scalef,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
let body =
|
let body =
|
||||||
Rect::new_sized_saturating(x + bw, y + bw, pos.width() - 2 * bw, pos.height() - 2 * bw);
|
Rect::new_sized_saturating(x + bw, y + bw, pos.width() - 2 * bw, pos.height() - 2 * bw);
|
||||||
let scissor_body = self.base.scale_rect(body);
|
let scissor_body = self.base.scale_rect(body);
|
||||||
if !cr.is_zero() {
|
if !cr.is_zero() {
|
||||||
let scalef = self.base.scalef as f32;
|
let inner_cr = self.scale_corner_radius(cr.expanded_by(-(bw as f32)));
|
||||||
let inner_cr = cr.expanded_by(-(bw as f32)).scaled_by(scalef);
|
|
||||||
self.corner_radius = Some(inner_cr);
|
self.corner_radius = Some(inner_cr);
|
||||||
}
|
}
|
||||||
child.node_render(self, body.x1(), body.y1(), Some(&scissor_body));
|
child.node_render(self, body.x1(), body.y1(), Some(&scissor_body));
|
||||||
|
|
|
||||||
|
|
@ -450,6 +450,7 @@ colors! {
|
||||||
focused_inactive_title_text = (0xff, 0xff, 0xff),
|
focused_inactive_title_text = (0xff, 0xff, 0xff),
|
||||||
separator = (0x33, 0x33, 0x33),
|
separator = (0x33, 0x33, 0x33),
|
||||||
border = (0x3f, 0x47, 0x4a),
|
border = (0x3f, 0x47, 0x4a),
|
||||||
|
active_border = (0x28, 0x55, 0x77),
|
||||||
bar_background = (0x00, 0x00, 0x00),
|
bar_background = (0x00, 0x00, 0x00),
|
||||||
bar_text = (0xff, 0xff, 0xff),
|
bar_text = (0xff, 0xff, 0xff),
|
||||||
attention_requested_background = (0x23, 0x09, 0x2c),
|
attention_requested_background = (0x23, 0x09, 0x2c),
|
||||||
|
|
@ -480,6 +481,7 @@ impl StaticText for ThemeColor {
|
||||||
ThemeColor::focused_inactive_title_text => "Title Text (focused, inactive)",
|
ThemeColor::focused_inactive_title_text => "Title Text (focused, inactive)",
|
||||||
ThemeColor::separator => "Separator",
|
ThemeColor::separator => "Separator",
|
||||||
ThemeColor::border => "Border",
|
ThemeColor::border => "Border",
|
||||||
|
ThemeColor::active_border => "Border (active)",
|
||||||
ThemeColor::bar_background => "Bar Background",
|
ThemeColor::bar_background => "Bar Background",
|
||||||
ThemeColor::bar_text => "Bar Text",
|
ThemeColor::bar_text => "Bar Text",
|
||||||
ThemeColor::attention_requested_background => "Attention Requested",
|
ThemeColor::attention_requested_background => "Attention Requested",
|
||||||
|
|
|
||||||
|
|
@ -389,17 +389,15 @@ impl ContainerNode {
|
||||||
let mb = self.mono_body.get();
|
let mb = self.mono_body.get();
|
||||||
return (mb.width(), mb.height());
|
return (mb.width(), mb.height());
|
||||||
}
|
}
|
||||||
let gap = self.state.theme.sizes.gap.get();
|
|
||||||
let bw = self.state.theme.sizes.border_width.get();
|
|
||||||
let nc = self.num_children.get() as i32 + 1;
|
let nc = self.num_children.get() as i32 + 1;
|
||||||
match self.split.get() {
|
match self.split.get() {
|
||||||
ContainerSplit::Horizontal => {
|
ContainerSplit::Horizontal => {
|
||||||
let spacing = gap.max(bw);
|
let spacing = self.child_spacing();
|
||||||
let content_w = self.width.get().sub((nc - 1) * spacing).max(0);
|
let content_w = self.width.get().sub((nc - 1) * spacing).max(0);
|
||||||
(content_w / nc, self.height.get())
|
(content_w / nc, self.height.get())
|
||||||
}
|
}
|
||||||
ContainerSplit::Vertical => {
|
ContainerSplit::Vertical => {
|
||||||
let spacing = gap.max(bw);
|
let spacing = self.child_spacing();
|
||||||
let content_h = self.height.get().sub((nc - 1) * spacing).max(0);
|
let content_h = self.height.get().sub((nc - 1) * spacing).max(0);
|
||||||
(self.width.get(), content_h / nc)
|
(self.width.get(), content_h / nc)
|
||||||
}
|
}
|
||||||
|
|
@ -431,6 +429,12 @@ impl ContainerNode {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn child_spacing(&self) -> i32 {
|
||||||
|
let gap = self.state.theme.sizes.gap.get();
|
||||||
|
let bw = self.state.theme.sizes.border_width.get();
|
||||||
|
if gap == 0 { bw } else { gap + 2 * bw }
|
||||||
|
}
|
||||||
|
|
||||||
fn schedule_layout(self: &Rc<Self>) {
|
fn schedule_layout(self: &Rc<Self>) {
|
||||||
if !self.layout_scheduled.replace(true) {
|
if !self.layout_scheduled.replace(true) {
|
||||||
self.state.pending_container_layout.push(self.clone());
|
self.state.pending_container_layout.push(self.clone());
|
||||||
|
|
@ -494,10 +498,8 @@ impl ContainerNode {
|
||||||
|
|
||||||
fn perform_split_layout(self: &Rc<Self>) {
|
fn perform_split_layout(self: &Rc<Self>) {
|
||||||
let sum_factors = self.sum_factors.get();
|
let sum_factors = self.sum_factors.get();
|
||||||
let gap = self.state.theme.sizes.gap.get();
|
|
||||||
let border_width = self.state.theme.sizes.border_width.get();
|
|
||||||
let split = self.split.get();
|
let split = self.split.get();
|
||||||
let spacing = gap.max(border_width);
|
let spacing = self.child_spacing();
|
||||||
let (content_size, other_content_size) = match split {
|
let (content_size, other_content_size) = match split {
|
||||||
ContainerSplit::Horizontal => (self.content_width.get(), self.content_height.get()),
|
ContainerSplit::Horizontal => (self.content_width.get(), self.content_height.get()),
|
||||||
ContainerSplit::Vertical => (self.content_height.get(), self.content_width.get()),
|
ContainerSplit::Vertical => (self.content_height.get(), self.content_width.get()),
|
||||||
|
|
@ -558,18 +560,15 @@ impl ContainerNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_content_size(&self) {
|
fn update_content_size(&self) {
|
||||||
let gap = self.state.theme.sizes.gap.get();
|
|
||||||
let border_width = self.state.theme.sizes.border_width.get();
|
|
||||||
let nc = self.num_children.get();
|
let nc = self.num_children.get();
|
||||||
|
let spacing = self.child_spacing();
|
||||||
match self.split.get() {
|
match self.split.get() {
|
||||||
ContainerSplit::Horizontal => {
|
ContainerSplit::Horizontal => {
|
||||||
let spacing = gap.max(border_width);
|
|
||||||
let new_content_size = self.width.get().sub((nc - 1) as i32 * spacing).max(0);
|
let new_content_size = self.width.get().sub((nc - 1) as i32 * spacing).max(0);
|
||||||
self.content_width.set(new_content_size);
|
self.content_width.set(new_content_size);
|
||||||
self.content_height.set(self.height.get());
|
self.content_height.set(self.height.get());
|
||||||
}
|
}
|
||||||
ContainerSplit::Vertical => {
|
ContainerSplit::Vertical => {
|
||||||
let spacing = gap.max(border_width);
|
|
||||||
let new_content_size = self.height.get().sub((nc - 1) as i32 * spacing).max(0);
|
let new_content_size = self.height.get().sub((nc - 1) as i32 * spacing).max(0);
|
||||||
self.content_height.set(new_content_size);
|
self.content_height.set(new_content_size);
|
||||||
self.content_width.set(self.width.get());
|
self.content_width.set(self.width.get());
|
||||||
|
|
@ -983,7 +982,9 @@ impl ContainerNode {
|
||||||
let was_ephemeral = self.ephemeral.replace(Ephemeral::Off);
|
let was_ephemeral = self.ephemeral.replace(Ephemeral::Off);
|
||||||
self.clone().cnode_remove_child2(&*focused_node, true);
|
self.clone().cnode_remove_child2(&*focused_node, true);
|
||||||
self.ephemeral.set(was_ephemeral);
|
self.ephemeral.set(was_ephemeral);
|
||||||
|
let focused_active = focused_node.tl_data().active();
|
||||||
let sub = ContainerNode::new(&self.state, &self.workspace.get(), focused_node, split);
|
let sub = ContainerNode::new(&self.state, &self.workspace.get(), focused_node, split);
|
||||||
|
let sub_id = sub.node_id();
|
||||||
if ephemeral {
|
if ephemeral {
|
||||||
sub.ephemeral.set(Ephemeral::On);
|
sub.ephemeral.set(Ephemeral::On);
|
||||||
}
|
}
|
||||||
|
|
@ -994,6 +995,11 @@ impl ContainerNode {
|
||||||
// Was the last child — append.
|
// Was the last child — append.
|
||||||
self.append_child(sub);
|
self.append_child(sub);
|
||||||
}
|
}
|
||||||
|
if focused_active
|
||||||
|
&& let Some(group) = self.child_nodes.borrow().get(&sub_id).map(|n| n.to_ref())
|
||||||
|
{
|
||||||
|
self.update_child_active(&group, true, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Change this container's split direction (hy3's `changegroup`).
|
/// Change this container's split direction (hy3's `changegroup`).
|
||||||
|
|
@ -1226,6 +1232,37 @@ impl ContainerNode {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let (split, prev) = direction_to_split(direction);
|
let (split, prev) = direction_to_split(direction);
|
||||||
|
if self.mono_child.is_some() && split == ContainerSplit::Horizontal {
|
||||||
|
let cc = match self.child_nodes.borrow().get(&child.node_id()) {
|
||||||
|
Some(l) => l.to_ref(),
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
let neighbor = match prev {
|
||||||
|
true => cc.prev(),
|
||||||
|
false => cc.next(),
|
||||||
|
};
|
||||||
|
if let Some(neighbor) = neighbor {
|
||||||
|
if let Some(cn) = neighbor.node.clone().node_into_container()
|
||||||
|
&& cn.cnode_accepts_child(&*child)
|
||||||
|
{
|
||||||
|
if let Some(mc) = self.mono_child.get()
|
||||||
|
&& mc.node.node_id() == child.node_id()
|
||||||
|
{
|
||||||
|
self.activate_child2(&neighbor, true);
|
||||||
|
}
|
||||||
|
self.cnode_remove_child2(&*child, true);
|
||||||
|
cn.insert_child_from_direction(child, direction);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
match prev {
|
||||||
|
true => neighbor.prepend_existing(&cc),
|
||||||
|
false => neighbor.append_existing(&cc),
|
||||||
|
}
|
||||||
|
self.rebuild_tab_bar();
|
||||||
|
self.damage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
// CASE 2: We're moving the child within the container.
|
// CASE 2: We're moving the child within the container.
|
||||||
if split == self.split.get()
|
if split == self.split.get()
|
||||||
|| (split == ContainerSplit::Horizontal && self.mono_child.is_some())
|
|| (split == ContainerSplit::Horizontal && self.mono_child.is_some())
|
||||||
|
|
@ -1248,7 +1285,7 @@ impl ContainerNode {
|
||||||
self.activate_child2(&neighbor, true);
|
self.activate_child2(&neighbor, true);
|
||||||
}
|
}
|
||||||
self.cnode_remove_child2(&*child, true);
|
self.cnode_remove_child2(&*child, true);
|
||||||
cn.insert_child(child, direction);
|
cn.insert_child_from_direction(child, direction);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
match prev {
|
match prev {
|
||||||
|
|
@ -1277,11 +1314,14 @@ impl ContainerNode {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.cnode_remove_child2(&*child, true);
|
let was_ephemeral = self.ephemeral.replace(Ephemeral::Off);
|
||||||
|
self.clone().cnode_remove_child2(&*child, true);
|
||||||
match prev {
|
match prev {
|
||||||
true => parent.add_child_before(&*neighbor, child.clone()),
|
true => parent.add_child_before(&*neighbor, child.clone()),
|
||||||
false => parent.add_child_after(&*neighbor, child.clone()),
|
false => parent.add_child_after(&*neighbor, child.clone()),
|
||||||
}
|
}
|
||||||
|
self.ephemeral.set(was_ephemeral);
|
||||||
|
self.collapse_ephemeral();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_child(self: &Rc<Self>, node: Rc<dyn ToplevelNode>, direction: Direction) {
|
pub fn insert_child(self: &Rc<Self>, node: Rc<dyn ToplevelNode>, direction: Direction) {
|
||||||
|
|
@ -1329,6 +1369,17 @@ impl ContainerNode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn insert_child_from_direction(
|
||||||
|
self: &Rc<Self>,
|
||||||
|
node: Rc<dyn ToplevelNode>,
|
||||||
|
direction: Direction,
|
||||||
|
) {
|
||||||
|
match direction {
|
||||||
|
Direction::Right | Direction::Down => self.prepend_child(node),
|
||||||
|
Direction::Left | Direction::Up | Direction::Unspecified => self.append_child(node),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn update_child_active(
|
fn update_child_active(
|
||||||
self: &Rc<Self>,
|
self: &Rc<Self>,
|
||||||
node: &NodeRef<ContainerChild>,
|
node: &NodeRef<ContainerChild>,
|
||||||
|
|
@ -1386,6 +1437,26 @@ impl ContainerNode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn collapse_ephemeral(self: &Rc<Self>) {
|
||||||
|
if self.ephemeral.get() != Ephemeral::On
|
||||||
|
|| self.num_children.get() != 1
|
||||||
|
|| self.toplevel_data.is_fullscreen.get()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if let Some(parent) = self.toplevel_data.parent.get()
|
||||||
|
&& let Some(only_child) = self.children.first()
|
||||||
|
{
|
||||||
|
let child_node = only_child.node.clone();
|
||||||
|
if parent.cnode_accepts_child(&*child_node) {
|
||||||
|
parent.cnode_replace_child(self.deref(), child_node);
|
||||||
|
self.toplevel_data.parent.take();
|
||||||
|
self.child_nodes.borrow_mut().clear();
|
||||||
|
self.tl_destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn mod_attention_requests(&self, set: bool) {
|
fn mod_attention_requests(&self, set: bool) {
|
||||||
let propagate = self.attention_requests.adj(set);
|
let propagate = self.attention_requests.adj(set);
|
||||||
if set || propagate {
|
if set || propagate {
|
||||||
|
|
@ -1722,7 +1793,6 @@ impl ContainerNode {
|
||||||
if let Some(s) = scale {
|
if let Some(s) = scale {
|
||||||
texture_height = (bar_height as f64 * s).round() as _;
|
texture_height = (bar_height as f64 * s).round() as _;
|
||||||
}
|
}
|
||||||
let mut scheduled = 0;
|
|
||||||
let mut texture_refs = Vec::new();
|
let mut texture_refs = Vec::new();
|
||||||
for (title, (_, _, text_color), title_texture) in &entries {
|
for (title, (_, _, text_color), title_texture) in &entries {
|
||||||
let mut tex_ref = title_texture.borrow_mut();
|
let mut tex_ref = title_texture.borrow_mut();
|
||||||
|
|
@ -1737,7 +1807,6 @@ impl ContainerNode {
|
||||||
scale,
|
scale,
|
||||||
);
|
);
|
||||||
texture_refs.push(title_texture.clone());
|
texture_refs.push(title_texture.clone());
|
||||||
scheduled += 1;
|
|
||||||
}
|
}
|
||||||
(on_completed.event(), texture_refs)
|
(on_completed.event(), texture_refs)
|
||||||
}
|
}
|
||||||
|
|
@ -2137,23 +2206,10 @@ impl ContainingNode for ContainerNode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.sum_factors.set(sum);
|
self.sum_factors.set(sum);
|
||||||
// Ephemeral collapse: if this container is ephemeral and has exactly
|
if self.ephemeral.get() == Ephemeral::On && num_children == 1 {
|
||||||
// one child remaining, replace this container with that child in the parent.
|
self.collapse_ephemeral();
|
||||||
if self.ephemeral.get() == Ephemeral::On
|
if self.toplevel_data.parent.is_none() {
|
||||||
&& num_children == 1
|
return;
|
||||||
&& !self.toplevel_data.is_fullscreen.get()
|
|
||||||
{
|
|
||||||
if let Some(parent) = self.toplevel_data.parent.get() {
|
|
||||||
if let Some(only_child) = self.children.first() {
|
|
||||||
let child_node = only_child.node.clone();
|
|
||||||
if parent.cnode_accepts_child(&*child_node) {
|
|
||||||
parent.cnode_replace_child(self.deref(), child_node);
|
|
||||||
self.toplevel_data.parent.take();
|
|
||||||
self.child_nodes.borrow_mut().clear();
|
|
||||||
self.tl_destroy();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// log::info!("cnode_remove_child2");
|
// log::info!("cnode_remove_child2");
|
||||||
|
|
@ -2234,8 +2290,6 @@ impl ContainingNode for ContainerNode {
|
||||||
new_y2: Option<i32>,
|
new_y2: Option<i32>,
|
||||||
) {
|
) {
|
||||||
let theme = &self.state.theme;
|
let theme = &self.state.theme;
|
||||||
let bw = theme.sizes.border_width.get();
|
|
||||||
let gap = theme.sizes.gap.get();
|
|
||||||
let mut left_outside = false;
|
let mut left_outside = false;
|
||||||
let mut right_outside = false;
|
let mut right_outside = false;
|
||||||
let mut top_outside = false;
|
let mut top_outside = false;
|
||||||
|
|
@ -2280,9 +2334,10 @@ impl ContainingNode for ContainerNode {
|
||||||
if ci == 0 {
|
if ci == 0 {
|
||||||
ci = 1;
|
ci = 1;
|
||||||
}
|
}
|
||||||
|
let between = self.child_spacing();
|
||||||
let (new_delta, between) = match split {
|
let (new_delta, between) = match split {
|
||||||
ContainerSplit::Horizontal => (self.abs_x1.get(), gap.max(bw)),
|
ContainerSplit::Horizontal => (self.abs_x1.get(), between),
|
||||||
ContainerSplit::Vertical => (self.abs_y1.get(), gap.max(bw)),
|
ContainerSplit::Vertical => (self.abs_y1.get(), between),
|
||||||
};
|
};
|
||||||
let new_i1 = new_i1.map(|v| v - new_delta);
|
let new_i1 = new_i1.map(|v| v - new_delta);
|
||||||
let new_i2 = new_i2.map(|v| v - new_delta);
|
let new_i2 = new_i2.map(|v| v - new_delta);
|
||||||
|
|
|
||||||
|
|
@ -213,6 +213,7 @@ pub struct Theme {
|
||||||
pub bar_bg_color: Option<Color>,
|
pub bar_bg_color: Option<Color>,
|
||||||
pub bar_status_text_color: Option<Color>,
|
pub bar_status_text_color: Option<Color>,
|
||||||
pub border_color: Option<Color>,
|
pub border_color: Option<Color>,
|
||||||
|
pub active_border_color: Option<Color>,
|
||||||
pub captured_focused_title_bg_color: Option<Color>,
|
pub captured_focused_title_bg_color: Option<Color>,
|
||||||
pub captured_unfocused_title_bg_color: Option<Color>,
|
pub captured_unfocused_title_bg_color: Option<Color>,
|
||||||
pub focused_inactive_title_bg_color: Option<Color>,
|
pub focused_inactive_title_bg_color: Option<Color>,
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,14 @@ impl Parser for ThemeParser<'_> {
|
||||||
font,
|
font,
|
||||||
title_font,
|
title_font,
|
||||||
),
|
),
|
||||||
(bar_font, bar_position_val, bar_separator_width, gap, floating_titles),
|
(
|
||||||
|
bar_font,
|
||||||
|
bar_position_val,
|
||||||
|
bar_separator_width,
|
||||||
|
gap,
|
||||||
|
floating_titles,
|
||||||
|
active_border_color,
|
||||||
|
),
|
||||||
) = ext.extract((
|
) = ext.extract((
|
||||||
(
|
(
|
||||||
opt(val("attention-requested-bg-color")),
|
opt(val("attention-requested-bg-color")),
|
||||||
|
|
@ -95,6 +102,7 @@ impl Parser for ThemeParser<'_> {
|
||||||
recover(opt(s32("bar-separator-width"))),
|
recover(opt(s32("bar-separator-width"))),
|
||||||
recover(opt(s32("gap"))),
|
recover(opt(s32("gap"))),
|
||||||
recover(opt(bol("floating-titles"))),
|
recover(opt(bol("floating-titles"))),
|
||||||
|
opt(val("active-border-color")),
|
||||||
),
|
),
|
||||||
))?;
|
))?;
|
||||||
let (title_gap, corner_radius) = ext.extract((
|
let (title_gap, corner_radius) = ext.extract((
|
||||||
|
|
@ -175,6 +183,7 @@ impl Parser for ThemeParser<'_> {
|
||||||
bar_bg_color: color!(bar_bg_color),
|
bar_bg_color: color!(bar_bg_color),
|
||||||
bar_status_text_color: color!(bar_status_text_color),
|
bar_status_text_color: color!(bar_status_text_color),
|
||||||
border_color: color!(border_color),
|
border_color: color!(border_color),
|
||||||
|
active_border_color: color!(active_border_color),
|
||||||
captured_focused_title_bg_color: color!(captured_focused_title_bg_color),
|
captured_focused_title_bg_color: color!(captured_focused_title_bg_color),
|
||||||
captured_unfocused_title_bg_color: color!(captured_unfocused_title_bg_color),
|
captured_unfocused_title_bg_color: color!(captured_unfocused_title_bg_color),
|
||||||
focused_inactive_title_bg_color: color!(focused_inactive_title_bg_color),
|
focused_inactive_title_bg_color: color!(focused_inactive_title_bg_color),
|
||||||
|
|
|
||||||
|
|
@ -990,6 +990,7 @@ impl State {
|
||||||
color!(BAR_BACKGROUND_COLOR, bar_bg_color);
|
color!(BAR_BACKGROUND_COLOR, bar_bg_color);
|
||||||
color!(BAR_STATUS_TEXT_COLOR, bar_status_text_color);
|
color!(BAR_STATUS_TEXT_COLOR, bar_status_text_color);
|
||||||
color!(BORDER_COLOR, border_color);
|
color!(BORDER_COLOR, border_color);
|
||||||
|
color!(ACTIVE_BORDER_COLOR, active_border_color);
|
||||||
color!(
|
color!(
|
||||||
CAPTURED_FOCUSED_TITLE_BACKGROUND_COLOR,
|
CAPTURED_FOCUSED_TITLE_BACKGROUND_COLOR,
|
||||||
captured_focused_title_bg_color
|
captured_focused_title_bg_color
|
||||||
|
|
|
||||||
|
|
@ -2137,6 +2137,10 @@
|
||||||
"description": "The color of the borders between windows.",
|
"description": "The color of the borders between windows.",
|
||||||
"$ref": "#/$defs/Color"
|
"$ref": "#/$defs/Color"
|
||||||
},
|
},
|
||||||
|
"active-border-color": {
|
||||||
|
"description": "The color of the borders around active windows.",
|
||||||
|
"$ref": "#/$defs/Color"
|
||||||
|
},
|
||||||
"captured-focused-title-bg-color": {
|
"captured-focused-title-bg-color": {
|
||||||
"description": "The background color of focused titles that are being recorded.",
|
"description": "The background color of focused titles that are being recorded.",
|
||||||
"$ref": "#/$defs/Color"
|
"$ref": "#/$defs/Color"
|
||||||
|
|
@ -2212,6 +2216,11 @@
|
||||||
"bar-font": {
|
"bar-font": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The name of the font to use in the bar. Defaults to `font` if not set."
|
"description": "The name of the font to use in the bar. Defaults to `font` if not set."
|
||||||
|
},
|
||||||
|
"corner-radius": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "The corner radius for window borders in logical pixels. Defaults to 0 (square corners).",
|
||||||
|
"minimum": 0.0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": []
|
"required": []
|
||||||
|
|
|
||||||
|
|
@ -4882,6 +4882,12 @@ The table has the following fields:
|
||||||
|
|
||||||
The value of this field should be a [Color](#types-Color).
|
The value of this field should be a [Color](#types-Color).
|
||||||
|
|
||||||
|
- `active-border-color` (optional):
|
||||||
|
|
||||||
|
The color of the borders around active windows.
|
||||||
|
|
||||||
|
The value of this field should be a [Color](#types-Color).
|
||||||
|
|
||||||
- `captured-focused-title-bg-color` (optional):
|
- `captured-focused-title-bg-color` (optional):
|
||||||
|
|
||||||
The background color of focused titles that are being recorded.
|
The background color of focused titles that are being recorded.
|
||||||
|
|
@ -5006,6 +5012,14 @@ The table has the following fields:
|
||||||
|
|
||||||
The value of this field should be a string.
|
The value of this field should be a string.
|
||||||
|
|
||||||
|
- `corner-radius` (optional):
|
||||||
|
|
||||||
|
The corner radius for window borders in logical pixels. Defaults to 0 (square corners).
|
||||||
|
|
||||||
|
The value of this field should be a number.
|
||||||
|
|
||||||
|
The numbers should be greater than or equal to 0.
|
||||||
|
|
||||||
|
|
||||||
<a name="types-TileState"></a>
|
<a name="types-TileState"></a>
|
||||||
### `TileState`
|
### `TileState`
|
||||||
|
|
|
||||||
|
|
@ -2346,6 +2346,10 @@ Theme:
|
||||||
ref: Color
|
ref: Color
|
||||||
required: false
|
required: false
|
||||||
description: The color of the borders between windows.
|
description: The color of the borders between windows.
|
||||||
|
active-border-color:
|
||||||
|
ref: Color
|
||||||
|
required: false
|
||||||
|
description: The color of the borders around active windows.
|
||||||
captured-focused-title-bg-color:
|
captured-focused-title-bg-color:
|
||||||
ref: Color
|
ref: Color
|
||||||
required: false
|
required: false
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue