1
0
Fork 0
forked from wry/wry

renderer: add support for floating-titlebars (#4)

Reviewed-on: https://git.kosslan.dev/wry/jay/pulls/4
This commit is contained in:
kossLAN 2026-04-06 20:58:36 -04:00 committed by atagen
parent 4d803360dd
commit 6dba659978
13 changed files with 316 additions and 158 deletions

View file

@ -277,65 +277,70 @@ impl Renderer<'_> {
self.render_tl_aux(placeholder.tl_data(), bounds, true);
}
pub fn render_container(&mut self, container: &ContainerNode, x: i32, y: i32) {
{
let srgb_srgb = self.state.color_manager.srgb_gamma22();
let srgb = &srgb_srgb.linear;
let perceptual = RenderIntent::Perceptual;
let rd = container.render_data.borrow_mut();
let c = self.state.theme.colors.unfocused_title_background.get();
fn render_container_decorations(&mut self, container: &ContainerNode, x: i32, y: i32) {
let srgb_srgb = self.state.color_manager.srgb_gamma22();
let srgb = &srgb_srgb.linear;
let perceptual = RenderIntent::Perceptual;
let rd = container.render_data.borrow_mut();
let c = self.state.theme.colors.unfocused_title_background.get();
self.base
.fill_boxes2(&rd.title_rects, &c, srgb, perceptual, x, y);
let c = self.state.theme.colors.focused_title_background.get();
self.base
.fill_boxes2(&rd.active_title_rects, &c, srgb, perceptual, x, y);
let c = self.state.theme.colors.attention_requested_background.get();
self.base
.fill_boxes2(&rd.attention_title_rects, &c, srgb, perceptual, x, y);
let c = self.state.theme.colors.separator.get();
self.base
.fill_boxes2(&rd.underline_rects, &c, srgb, perceptual, x, y);
let c = self.state.theme.colors.border.get();
self.base
.fill_boxes2(&rd.border_rects, &c, srgb, perceptual, x, y);
if let Some(lar) = &rd.last_active_rect {
let c = self
.state
.theme
.colors
.focused_inactive_title_background
.get();
self.base
.fill_boxes2(&rd.title_rects, &c, srgb, perceptual, x, y);
let c = self.state.theme.colors.focused_title_background.get();
self.base
.fill_boxes2(&rd.active_title_rects, &c, srgb, perceptual, x, y);
let c = self.state.theme.colors.attention_requested_background.get();
self.base
.fill_boxes2(&rd.attention_title_rects, &c, srgb, perceptual, x, y);
let c = self.state.theme.colors.separator.get();
self.base
.fill_boxes2(&rd.underline_rects, &c, srgb, perceptual, x, y);
let c = self.state.theme.colors.border.get();
self.base
.fill_boxes2(&rd.border_rects, &c, srgb, perceptual, x, y);
if let Some(lar) = &rd.last_active_rect {
let c = self
.state
.theme
.colors
.focused_inactive_title_background
.get();
self.base
.fill_boxes2(std::slice::from_ref(lar), &c, srgb, perceptual, x, y);
}
if let Some(titles) = rd.titles.get(&self.base.scale) {
for title in titles {
let rect = title.rect.move_(x, y);
let bounds = self.base.scale_rect(rect);
let (x, y) = self.base.scale_point(rect.x1(), rect.y1());
self.base.render_texture(
&title.tex,
None,
x,
y,
None,
None,
self.base.scale,
Some(&bounds),
None,
AcquireSync::None,
ReleaseSync::None,
false,
srgb_srgb,
perceptual,
AlphaMode::PremultipliedElectrical,
);
}
.fill_boxes2(std::slice::from_ref(lar), &c, srgb, perceptual, x, y);
}
if let Some(titles) = rd.titles.get(&self.base.scale) {
for title in titles {
let rect = title.rect.move_(x, y);
let bounds = self.base.scale_rect(rect);
let (x, y) = self.base.scale_point(rect.x1(), rect.y1());
self.base.render_texture(
&title.tex,
None,
x,
y,
None,
None,
self.base.scale,
Some(&bounds),
None,
AcquireSync::None,
ReleaseSync::None,
false,
srgb_srgb,
perceptual,
AlphaMode::PremultipliedElectrical,
);
}
}
}
pub fn render_container(&mut self, container: &ContainerNode, x: i32, y: i32) {
let floating = self.state.theme.floating_titles.get();
self.render_container_decorations(container, x, y);
if let Some(child) = container.mono_child.get() {
let mb = container.mono_body.get();
if self.state.theme.sizes.gap.get() > 0 && !child.node.node_is_container() {
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 border_color = self.state.theme.colors.border.get();
@ -346,22 +351,48 @@ impl Renderer<'_> {
} else {
&border_color
};
let full_h = mb.y2();
let full_w = mb.width();
let frame_rects = [
Rect::new_sized_saturating(mb.x1() - bw, 0, bw, full_h),
Rect::new_sized_saturating(mb.x2(), 0, bw, full_h),
Rect::new_sized_saturating(mb.x1() - bw, -bw, full_w + 2 * bw, bw),
Rect::new_sized_saturating(mb.x1() - bw, full_h, full_w + 2 * bw, bw),
];
self.base.fill_boxes2(
&frame_rects,
c,
&srgb_srgb.linear,
RenderIntent::Perceptual,
x,
y,
);
let srgb = &srgb_srgb.linear;
let perceptual = RenderIntent::Perceptual;
if floating {
if !child.node.node_is_container() {
let body_frame = [
Rect::new_sized_saturating(mb.x1() - bw, mb.y1(), bw, mb.y2() - mb.y1()),
Rect::new_sized_saturating(mb.x2(), mb.y1(), bw, mb.y2() - mb.y1()),
Rect::new_sized_saturating(mb.x1() - bw, mb.y1() - bw, full_w + 2 * bw, bw),
Rect::new_sized_saturating(mb.x1() - bw, mb.y2(), full_w + 2 * bw, bw),
];
self.base.fill_boxes2(&body_frame, c, srgb, perceptual, x, y);
}
let th = self.state.theme.title_height();
if th > 0 {
for tab in container.children.iter() {
let tr = tab.title_rect.get();
let tc = if tab.active.get() {
&focused_border_color
} else {
&border_color
};
let tw = tr.width();
let tab_frame = [
Rect::new_sized_saturating(tr.x1() - bw, tr.y1() - bw, tw + 2 * bw, bw),
Rect::new_sized_saturating(tr.x1() - bw, tr.y1(), bw, th),
Rect::new_sized_saturating(tr.x2(), tr.y1(), bw, th),
Rect::new_sized_saturating(tr.x1() - bw, tr.y1() + th, tw + 2 * bw, bw),
];
self.base.fill_boxes2(&tab_frame, tc, srgb, perceptual, x, y);
}
}
} else if !child.node.node_is_container() {
let full_h = mb.y2();
let frame_rects = [
Rect::new_sized_saturating(mb.x1() - bw, 0, bw, full_h),
Rect::new_sized_saturating(mb.x2(), 0, bw, full_h),
Rect::new_sized_saturating(mb.x1() - bw, -bw, full_w + 2 * bw, bw),
Rect::new_sized_saturating(mb.x1() - bw, full_h, full_w + 2 * bw, bw),
];
self.base.fill_boxes2(&frame_rects, c, srgb, perceptual, x, y);
}
}
let body = mb.move_(x, y);
let body = self.base.scale_rect(body);
@ -371,7 +402,7 @@ impl Renderer<'_> {
.node_render(self, x + content.x1(), y + content.y1(), Some(&body));
} else {
let gap = self.state.theme.sizes.gap.get();
let (srgb_srgb, bw, border_color, focused_border_color, tpuh) = if gap > 0 {
let (srgb_srgb, bw, border_color, focused_border_color, tpuh) = if gap != 0 {
let srgb_srgb = self.state.color_manager.srgb_gamma22();
let bw = self.state.theme.sizes.border_width.get();
let border_color = self.state.theme.colors.border.get();
@ -393,41 +424,46 @@ impl Renderer<'_> {
break;
}
if let Some(srgb_srgb) = srgb_srgb {
if !child.node.node_is_container() {
let srgb = &srgb_srgb.linear;
let c = if child.border_color_is_focused.get() {
&focused_border_color
} else {
&border_color
};
let title_rect = child.title_rect.get();
let srgb = &srgb_srgb.linear;
let c = if floating {
if child.active.get() { &focused_border_color } else { &border_color }
} else if child.border_color_is_focused.get() {
&focused_border_color
} else {
&border_color
};
let title_rect = child.title_rect.get();
let full_w = body.width();
let perceptual = RenderIntent::Perceptual;
if floating && tpuh > 0 {
let tw = title_rect.width();
let title_h = title_rect.height();
let title_frame = [
Rect::new_sized_saturating(title_rect.x1() - bw, title_rect.y1() - bw, tw + 2 * bw, bw),
Rect::new_sized_saturating(title_rect.x1() - bw, title_rect.y1(), bw, title_h),
Rect::new_sized_saturating(title_rect.x2(), title_rect.y1(), bw, title_h),
Rect::new_sized_saturating(title_rect.x1() - bw, title_rect.y1() + title_h, tw + 2 * bw, bw),
];
self.base.fill_boxes2(&title_frame, c, srgb, perceptual, x, y);
if !child.node.node_is_container() && gap != 0 {
let body_frame = [
Rect::new_sized_saturating(body.x1() - bw, body.y1(), bw, body.y2() - body.y1()),
Rect::new_sized_saturating(body.x2(), body.y1(), bw, body.y2() - body.y1()),
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(&body_frame, c, srgb, perceptual, x, y);
}
} else if !child.node.node_is_container() && gap != 0 {
let top_y = if tpuh > 0 { title_rect.y1() } else { body.y1() };
let full_h = body.y2() - top_y;
let full_w = body.width();
let frame_rects = [
Rect::new_sized_saturating(body.x1() - bw, top_y, bw, full_h),
Rect::new_sized_saturating(body.x2(), top_y, bw, full_h),
Rect::new_sized_saturating(
body.x1() - bw,
top_y - bw,
full_w + 2 * bw,
bw,
),
Rect::new_sized_saturating(
body.x1() - bw,
body.y2(),
full_w + 2 * bw,
bw,
),
Rect::new_sized_saturating(body.x1() - bw, top_y - 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,
RenderIntent::Perceptual,
x,
y,
);
self.base.fill_boxes2(&frame_rects, c, srgb, perceptual, x, y);
}
}
let body = body.move_(x, y);
@ -438,6 +474,7 @@ impl Renderer<'_> {
.node_render(self, x + content.x1(), y + content.y1(), Some(&body));
}
}
self.render_tl_aux(container.tl_data(), None, false);
}