1
0
Fork 0
forked from wry/wry

config: allow disabling window titles

This commit is contained in:
Sean Day 2025-10-16 17:48:47 +02:00 committed by Julian Orth
parent 796269d31e
commit daafb98336
19 changed files with 222 additions and 74 deletions

View file

@ -1381,6 +1381,17 @@ impl ConfigProxyHandler {
});
}
fn handle_set_show_titles(&self, show: bool) {
self.state.theme.show_titles.set(show);
self.spaces_change();
}
fn handle_get_show_titles(&self) {
self.respond(Response::GetShowTitles {
show: self.state.theme.show_titles.get(),
});
}
fn handle_set_show_float_pin_icon(&self, show: bool) {
self.state.show_pin_icon.set(show);
for stacked in self.state.root.stacked.iter() {
@ -3188,6 +3199,8 @@ impl ConfigProxyHandler {
.wrn("get_content_type")?,
ClientMessage::SetShowBar { show } => self.handle_set_show_bar(show),
ClientMessage::GetShowBar => self.handle_get_show_bar(),
ClientMessage::SetShowTitles { show } => self.handle_set_show_titles(show),
ClientMessage::GetShowTitles => self.handle_get_show_titles(),
ClientMessage::SeatFocusHistory { seat, timeline } => self
.handle_seat_focus_history(seat, timeline)
.wrn("seat_focus_history")?,

View file

@ -49,7 +49,7 @@ pub enum IconsError {
impl Icons {
pub fn update_sizes(&self, state: &State) {
let mut sizes = AHashSet::new();
let height = state.theme.sizes.title_height.get();
let height = state.theme.title_height();
for &(scale, _) in &*state.scales.lock() {
let [size] = scale.pixel_size([height]);
if size > 0 {
@ -64,7 +64,7 @@ impl Icons {
}
pub fn get(&self, state: &State, scale: Scale) -> Option<Rc<SizedIcons>> {
let [size] = scale.pixel_size([state.theme.sizes.title_height.get()]);
let [size] = scale.pixel_size([state.theme.title_height()]);
if let Some(icons) = self.icons.get(&size) {
return icons;
}

View file

@ -21,14 +21,14 @@ async fn test(run: Rc<TestRun>) -> Result<(), TestError> {
tassert_eq!(window.tl.core.width.get(), 800);
tassert_eq!(
window.tl.core.height.get(),
600 - 2 * (run.state.theme.sizes.title_height.get() + 1)
600 - 2 * run.state.theme.title_plus_underline_height()
);
tassert_eq!(
window.tl.server.node_absolute_position(),
Rect::new_sized(
0,
2 * (run.state.theme.sizes.title_height.get() + 1),
2 * run.state.theme.title_plus_underline_height(),
window.tl.core.width.get(),
window.tl.core.height.get(),
)

View file

@ -21,7 +21,7 @@ async fn test(run: Rc<TestRun>) -> Result<(), TestError> {
let window2 = client.create_window().await?;
window2.map().await?;
let otop = 2 * (run.state.theme.sizes.title_height.get() + 1);
let otop = 2 * run.state.theme.title_plus_underline_height();
let bw = run.state.theme.sizes.border_width.get();
tassert_eq!(

View file

@ -501,7 +501,9 @@ impl Renderer<'_> {
};
let pos = floating.position.get();
let theme = &self.state.theme;
let th = theme.sizes.title_height.get();
let th = theme.title_height();
let tpuh = theme.title_plus_underline_height();
let tuh = theme.title_underline_height();
let bw = theme.sizes.border_width.get();
let bc = theme.colors.border.get();
let tc = if floating.active.get() {
@ -524,7 +526,7 @@ impl Renderer<'_> {
let title = [Rect::new_sized(x + bw, y + bw, pos.width() - 2 * bw, th).unwrap()];
self.base.fill_boxes(&title, &tc, srgb);
let title_underline =
[Rect::new_sized(x + bw, y + bw + th, pos.width() - 2 * bw, 1).unwrap()];
[Rect::new_sized(x + bw, y + bw + th, pos.width() - 2 * bw, tuh).unwrap()];
self.base.fill_boxes(&title_underline, &uc, srgb);
let rect = floating.title_rect.get().move_(x, y);
let bounds = self.base.scale_rect(rect);
@ -584,9 +586,9 @@ impl Renderer<'_> {
}
let body = Rect::new_sized(
x + bw,
y + bw + th + 1,
y + bw + tpuh,
pos.width() - 2 * bw,
pos.height() - 2 * bw - th - 1,
pos.height() - 2 * bw - tpuh,
)
.unwrap();
let scissor_body = self.base.scale_rect(body);

View file

@ -826,7 +826,8 @@ impl State {
abs_pos: Option<(i32, i32)>,
) {
width += 2 * self.theme.sizes.border_width.get();
height += 2 * self.theme.sizes.border_width.get() + self.theme.sizes.title_height.get() + 1;
height +=
2 * self.theme.sizes.border_width.get() + self.theme.title_plus_underline_height();
let output = workspace.output.get();
let output_rect = output.global.pos.get();
let position = if let Some((mut x1, mut y1)) = abs_pos {
@ -836,7 +837,7 @@ impl State {
if y1 > output_rect.y2() {
y1 = output_rect.y2();
}
y1 -= self.theme.sizes.border_width.get() + self.theme.sizes.title_height.get() + 1;
y1 -= self.theme.sizes.border_width.get() + self.theme.title_plus_underline_height();
x1 -= self.theme.sizes.border_width.get();
Rect::new_sized(x1, y1, width, height).unwrap()
} else {

View file

@ -466,6 +466,7 @@ pub struct Theme {
pub bar_font: CloneCell<Option<Arc<String>>>,
pub title_font: CloneCell<Option<Arc<String>>>,
pub default_font: Arc<String>,
pub show_titles: Cell<bool>,
}
impl Default for Theme {
@ -478,6 +479,7 @@ impl Default for Theme {
bar_font: Default::default(),
title_font: Default::default(),
default_font,
show_titles: Cell::new(true),
}
}
}
@ -490,4 +492,24 @@ impl Theme {
pub fn bar_font(&self) -> Arc<String> {
self.bar_font.get().unwrap_or_else(|| self.font.get())
}
pub fn title_height(&self) -> i32 {
if self.show_titles.get() {
self.sizes.title_height.get()
} else {
0
}
}
pub fn title_underline_height(&self) -> i32 {
if self.show_titles.get() { 1 } else { 0 }
}
pub fn title_plus_underline_height(&self) -> i32 {
if self.show_titles.get() {
self.sizes.title_height.get() + 1
} else {
0
}
}
}

View file

@ -426,7 +426,7 @@ impl ContainerNode {
self.mono_content
.set(child.content.get().at_point(mb.x1(), mb.y1()));
let th = self.state.theme.sizes.title_height.get();
let th = self.state.theme.title_height();
let bw = self.state.theme.sizes.border_width.get();
let num_children = self.num_children.get() as i32;
let content_width = self.width.get().sub(bw * (num_children - 1)).max(0);
@ -449,7 +449,8 @@ impl ContainerNode {
fn perform_split_layout(self: &Rc<Self>) {
let sum_factors = self.sum_factors.get();
let border_width = self.state.theme.sizes.border_width.get();
let title_height = self.state.theme.sizes.title_height.get();
let title_height_tmp = self.state.theme.title_height();
let title_plus_underline_height = self.state.theme.title_plus_underline_height();
let split = self.split.get();
let (content_size, other_content_size) = match split {
ContainerSplit::Horizontal => (self.content_width.get(), self.content_height.get()),
@ -468,16 +469,24 @@ impl ContainerNode {
body_size = body_size.min(remaining_content_size);
remaining_content_size -= body_size;
let (x1, y1, width, height) = match split {
ContainerSplit::Horizontal => {
(pos, title_height + 1, body_size, other_content_size)
}
_ => (0, pos + title_height + 1, other_content_size, body_size),
ContainerSplit::Horizontal => (
pos,
title_plus_underline_height,
body_size,
other_content_size,
),
_ => (
0,
pos + title_plus_underline_height,
other_content_size,
body_size,
),
};
let body = Rect::new_sized(x1, y1, width, height).unwrap();
child.body.set(body);
pos += body_size + border_width;
if split == ContainerSplit::Vertical {
pos += title_height + 1;
pos += title_plus_underline_height;
}
}
if remaining_content_size > 0 {
@ -494,13 +503,19 @@ impl ContainerNode {
let (x1, y1, width, height, size) = match split {
ContainerSplit::Horizontal => {
let width = body.width() + add;
(pos, title_height + 1, width, other_content_size, width)
(
pos,
title_plus_underline_height,
width,
other_content_size,
width,
)
}
_ => {
let height = body.height() + add;
(
0,
pos + title_height + 1,
pos + title_plus_underline_height,
other_content_size,
height,
height,
@ -511,7 +526,7 @@ impl ContainerNode {
child.body.set(body);
pos += size + border_width;
if split == ContainerSplit::Vertical {
pos += title_height + 1;
pos += title_plus_underline_height;
}
}
}
@ -521,9 +536,9 @@ impl ContainerNode {
child.title_rect.set(
Rect::new_sized(
body.x1(),
body.y1() - title_height - 1,
body.y1() - title_plus_underline_height,
body.width(),
title_height,
title_height_tmp,
)
.unwrap(),
);
@ -535,20 +550,23 @@ impl ContainerNode {
fn update_content_size(&self) {
let border_width = self.state.theme.sizes.border_width.get();
let title_height = self.state.theme.sizes.title_height.get();
let title_plus_underline_height = self.state.theme.title_plus_underline_height();
let nc = self.num_children.get();
match self.split.get() {
ContainerSplit::Horizontal => {
let new_content_size = self.width.get().sub((nc - 1) as i32 * border_width).max(0);
self.content_width.set(new_content_size);
self.content_height
.set(self.height.get().sub(title_height + 1).max(0));
.set(self.height.get().sub(title_plus_underline_height).max(0));
}
ContainerSplit::Vertical => {
let new_content_size = self
.height
.get()
.sub(title_height + 1 + (nc - 1) as i32 * (border_width + title_height + 1))
.sub(
title_plus_underline_height
+ (nc - 1) as i32 * (border_width + title_plus_underline_height),
)
.max(0);
self.content_height.set(new_content_size);
self.content_width.set(self.width.get());
@ -557,9 +575,9 @@ impl ContainerNode {
self.mono_body.set(
Rect::new_sized(
0,
title_height + 1,
title_plus_underline_height,
self.width.get(),
self.height.get().sub(title_height + 1).max(0),
self.height.get().sub(title_plus_underline_height).max(0),
)
.unwrap(),
);
@ -576,7 +594,7 @@ impl ContainerNode {
) {
let mut x = x.round_down();
let mut y = y.round_down();
let title_height = self.state.theme.sizes.title_height.get();
let title_plus_underline_height = self.state.theme.title_plus_underline_height();
let mut seats = self.cursors.borrow_mut();
let seat_state = seats.entry(id).or_insert_with(|| CursorState {
cursor: KnownCursor::Default,
@ -648,7 +666,7 @@ impl ContainerNode {
let new_cursor = if self.mono_child.is_some() {
KnownCursor::Default
} else if self.split.get() == ContainerSplit::Horizontal {
if y < title_height + 1 {
if y < title_plus_underline_height {
KnownCursor::Default
} else {
KnownCursor::EwResize
@ -658,7 +676,7 @@ impl ContainerNode {
for child in self.children.iter() {
let body = child.body.get();
if body.y1() > y {
if body.y1() - y > title_height + 1 {
if body.y1() - y > title_plus_underline_height {
cursor = KnownCursor::NsResize
}
break;
@ -706,7 +724,7 @@ impl ContainerNode {
return on_completed.event();
};
let theme = &self.state.theme;
let th = theme.sizes.title_height.get();
let th = theme.title_height();
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());
@ -794,7 +812,9 @@ impl ContainerNode {
let mut rd = self.render_data.borrow_mut();
let rd = rd.deref_mut();
let theme = &self.state.theme;
let th = theme.sizes.title_height.get();
let th = theme.title_height();
let tpuh = theme.title_plus_underline_height();
let tuh = theme.title_underline_height();
let bw = theme.sizes.border_width.get();
let cwidth = self.width.get();
let cheight = self.height.get();
@ -820,7 +840,7 @@ impl ContainerNode {
abs_x,
abs_y + rect.y1(),
cwidth,
rect.height() + 1,
rect.height() + tuh,
));
}
if i > 0 {
@ -856,11 +876,11 @@ impl ContainerNode {
}
if mono {
rd.underline_rects
.push(Rect::new_sized(0, th, cwidth, 1).unwrap());
.push(Rect::new_sized(0, th, cwidth, tuh).unwrap());
}
if self.toplevel_data.visible.get() && (mono || split == ContainerSplit::Horizontal) {
self.state
.damage(Rect::new_sized_unchecked(abs_x, abs_y, cwidth, th + 1));
.damage(Rect::new_sized_unchecked(abs_x, abs_y, cwidth, tpuh));
}
rd.titles.remove_if(|_, v| v.is_empty());
}
@ -1193,7 +1213,7 @@ impl ContainerNode {
};
if button == BTN_RIGHT && pressed {
if self.mono_child.is_some() || self.split.get() == ContainerSplit::Horizontal {
if seat_data.y < self.state.theme.sizes.title_height.get() {
if seat_data.y < self.state.theme.title_height() {
self.toggle_mono();
}
} else {
@ -1314,7 +1334,7 @@ impl ContainerNode {
prev_center,
0,
self.width.get(),
self.state.theme.sizes.title_height.get(),
self.state.theme.title_height(),
)?
.move_(self.abs_x1.get(), self.abs_y1.get())
.intersect(abs_bounds);
@ -1339,7 +1359,7 @@ impl ContainerNode {
abs_x: i32,
abs_y: i32,
) -> Option<TileDragDestination> {
let th = self.state.theme.sizes.title_height.get();
let th = self.state.theme.title_height();
if abs_y < self.abs_y1.get() + th {
return self.tile_drag_destination_mono_titles(source, abs_bounds, abs_x, abs_y);
}
@ -1694,7 +1714,7 @@ impl Node for ContainerNode {
Some(s) => s,
_ => return,
};
if seat_data.y > self.state.theme.sizes.title_height.get() {
if seat_data.y > self.state.theme.title_height() {
return;
}
let cur_mc = match self.mono_child.get() {
@ -1984,9 +2004,9 @@ impl ContainingNode for ContainerNode {
let Some(parent) = self.toplevel_data.parent.get() else {
return;
};
let th = self.state.theme.sizes.title_height.get();
let tpuh = self.state.theme.title_plus_underline_height();
if self.mono_child.is_some() {
parent.cnode_set_child_position(&*self, x, y - th - 1);
parent.cnode_set_child_position(&*self, x, y - tpuh);
} else {
let children = self.child_nodes.borrow();
let Some(child) = children.get(&child.node_id()) else {
@ -2007,7 +2027,7 @@ impl ContainingNode for ContainerNode {
new_y2: Option<i32>,
) {
let theme = &self.state.theme;
let th = theme.sizes.title_height.get();
let tpuh = theme.title_plus_underline_height();
let bw = theme.sizes.border_width.get();
let mut left_outside = false;
let mut right_outside = false;
@ -2049,7 +2069,7 @@ impl ContainingNode for ContainerNode {
}
let (new_delta, between) = match split {
ContainerSplit::Horizontal => (self.abs_x1.get(), bw),
ContainerSplit::Vertical => (self.abs_y1.get(), bw + th + 1),
ContainerSplit::Vertical => (self.abs_y1.get(), bw + tpuh),
};
let new_i1 = new_i1.map(|v| v - new_delta);
let new_i2 = new_i2.map(|v| v - new_delta);
@ -2117,10 +2137,10 @@ impl ContainingNode for ContainerNode {
x2 = new_x2.map(|v| v.max(x1.unwrap_or(pos.x1())));
}
if top_outside {
y1 = new_y1.map(|v| (v - th - 1).min(pos.y2() - th - 1));
y1 = new_y1.map(|v| (v - tpuh).min(pos.y2() - tpuh));
}
if bottom_outside {
y2 = new_y2.map(|v| v.max(y1.unwrap_or(pos.y1()) + th + 1));
y2 = new_y2.map(|v| v.max(y1.unwrap_or(pos.y1()) + tpuh));
}
if ((x1.is_some() && x1 != Some(pos.x1()))
|| (x2.is_some() && x2 != Some(pos.x2()))

View file

@ -177,12 +177,13 @@ impl FloatNode {
let pos = self.position.get();
let theme = &self.state.theme;
let bw = theme.sizes.border_width.get();
let th = theme.sizes.title_height.get();
let th = theme.title_height();
let tpuh = theme.title_plus_underline_height();
let cpos = Rect::new_sized(
pos.x1() + bw,
pos.y1() + bw + th + 1,
pos.y1() + bw + tpuh,
(pos.width() - 2 * bw).max(0),
(pos.height() - 2 * bw - th - 1).max(0),
(pos.height() - 2 * bw - tpuh).max(0),
)
.unwrap();
let tr = Rect::new_sized(bw, bw, (pos.width() - 2 * bw).max(0), th).unwrap();
@ -248,7 +249,7 @@ impl FloatNode {
fn render_title_phase2(&self) {
let theme = &self.state.theme;
let th = theme.sizes.title_height.get();
let th = theme.title_height();
let bw = theme.sizes.border_width.get();
let title = self.title.borrow();
let tt = &*self.title_textures.borrow();
@ -277,7 +278,7 @@ impl FloatNode {
let y = y.round_down();
let theme = &self.state.theme;
let bw = theme.sizes.border_width.get();
let th = theme.sizes.title_height.get();
let tpuh = theme.title_plus_underline_height();
let mut seats = self.cursors.borrow_mut();
let seat_state = seats.entry(id).or_insert_with(|| CursorState {
cursor: KnownCursor::Default,
@ -313,7 +314,7 @@ impl FloatNode {
}
OpType::ResizeTop => {
y1 += y - seat_state.dist_ver;
y1 = y1.min(y2 - 2 * bw - th - 1);
y1 = y1.min(y2 - 2 * bw - tpuh);
}
OpType::ResizeRight => {
x2 += x - pos.width() + seat_state.dist_hor;
@ -321,31 +322,31 @@ impl FloatNode {
}
OpType::ResizeBottom => {
y2 += y - pos.height() + seat_state.dist_ver;
y2 = y2.max(y1 + 2 * bw + th + 1);
y2 = y2.max(y1 + 2 * bw + tpuh);
}
OpType::ResizeTopLeft => {
x1 += x - seat_state.dist_hor;
y1 += y - seat_state.dist_ver;
x1 = x1.min(x2 - 2 * bw);
y1 = y1.min(y2 - 2 * bw - th - 1);
y1 = y1.min(y2 - 2 * bw - tpuh);
}
OpType::ResizeTopRight => {
x2 += x - pos.width() + seat_state.dist_hor;
y1 += y - seat_state.dist_ver;
x2 = x2.max(x1 + 2 * bw);
y1 = y1.min(y2 - 2 * bw - th - 1);
y1 = y1.min(y2 - 2 * bw - tpuh);
}
OpType::ResizeBottomLeft => {
x1 += x - seat_state.dist_hor;
y2 += y - pos.height() + seat_state.dist_ver;
x1 = x1.min(x2 - 2 * bw);
y2 = y2.max(y1 + 2 * bw + th + 1);
y2 = y2.max(y1 + 2 * bw + tpuh);
}
OpType::ResizeBottomRight => {
x2 += x - pos.width() + seat_state.dist_hor;
y2 += y - pos.height() + seat_state.dist_ver;
x2 = x2.max(x1 + 2 * bw);
y2 = y2.max(y1 + 2 * bw + th + 1);
y2 = y2.max(y1 + 2 * bw + tpuh);
}
}
let new_pos = Rect::new(x1, y1, x2, y2).unwrap();
@ -438,7 +439,7 @@ impl FloatNode {
return;
}
let bw = self.state.theme.sizes.border_width.get();
let th = self.state.theme.sizes.title_height.get();
let th = self.state.theme.title_height();
let mut x1 = pos.x1();
let mut x2 = pos.x2();
let mut y1 = pos.y1();
@ -553,7 +554,7 @@ impl FloatNode {
_ => return,
};
let bw = self.state.theme.sizes.border_width.get();
let th = self.state.theme.sizes.title_height.get();
let th = self.state.theme.title_height();
let mut is_icon_press = false;
if pressed && cursor_data.x >= bw && cursor_data.y >= bw && cursor_data.y < bw + th {
enum FloatIcon {
@ -647,11 +648,11 @@ impl FloatNode {
let child = self.child.get()?;
let theme = &self.state.theme.sizes;
let bw = theme.border_width.get();
let th = theme.title_height.get();
let tpuh = self.state.theme.title_plus_underline_height();
let pos = self.position.get();
let body = Rect::new(
pos.x1() + bw,
pos.y1() + bw + th + 1,
pos.y1() + bw + tpuh,
pos.x2() - bw,
pos.y2() - bw,
)?;
@ -732,13 +733,13 @@ impl Node for FloatNode {
usecase: FindTreeUsecase,
) -> FindTreeResult {
let theme = &self.state.theme;
let th = theme.sizes.title_height.get();
let tpuh = theme.title_plus_underline_height();
let bw = theme.sizes.border_width.get();
let pos = self.position.get();
if x < bw || x >= pos.width() - bw {
return FindTreeResult::AcceptsInput;
}
if y < bw + th + 1 || y >= pos.height() - bw {
if y < bw + tpuh || y >= pos.height() - bw {
return FindTreeResult::AcceptsInput;
}
let child = match self.child.get() {
@ -746,7 +747,7 @@ impl Node for FloatNode {
_ => return FindTreeResult::Other,
};
let x = x - bw;
let y = y - bw - th - 1;
let y = y - bw - tpuh;
tree.push(FoundNode {
node: child.clone(),
x,
@ -928,9 +929,9 @@ impl ContainingNode for FloatNode {
fn cnode_set_child_position(self: Rc<Self>, _child: &dyn Node, x: i32, y: i32) {
let theme = &self.state.theme;
let th = theme.sizes.title_height.get();
let tpuh = theme.title_plus_underline_height();
let bw = theme.sizes.border_width.get();
let (x, y) = (x - bw, y - th - bw - 1);
let (x, y) = (x - bw, y - tpuh - bw);
let pos = self.position.get();
if pos.position() != (x, y) {
let new_pos = pos.at_point(x, y);
@ -950,7 +951,7 @@ impl ContainingNode for FloatNode {
new_y2: Option<i32>,
) {
let theme = &self.state.theme;
let th = theme.sizes.title_height.get();
let tpuh = theme.title_plus_underline_height();
let bw = theme.sizes.border_width.get();
let pos = self.position.get();
let mut x1 = pos.x1();
@ -964,10 +965,10 @@ impl ContainingNode for FloatNode {
x2 = (v + bw).max(x1 + bw + bw);
}
if let Some(v) = new_y1 {
y1 = (v - th - bw - 1).min(y2 - bw - th - bw - 1);
y1 = (v - tpuh - bw).min(y2 - bw - tpuh - bw);
}
if let Some(v) = new_y2 {
y2 = (v + bw).max(y1 + bw + th + bw + 1);
y2 = (v + bw).max(y1 + bw + tpuh + bw);
}
let new_pos = Rect::new(x1, y1, x2, y2).unwrap();
if new_pos != pos {