diff --git a/i4config/src/lib.rs b/i4config/src/lib.rs index 88c2f7eb..13a04fd3 100644 --- a/i4config/src/lib.rs +++ b/i4config/src/lib.rs @@ -22,7 +22,7 @@ pub enum LogLevel { Trace, } -#[derive(Encode, Decode, Copy, Clone, Debug)] +#[derive(Encode, Decode, Copy, Clone, Debug, Eq, PartialEq)] pub enum Direction { Left, Down, diff --git a/src/ifs/wl_surface.rs b/src/ifs/wl_surface.rs index 0b65d46e..233c1ba1 100644 --- a/src/ifs/wl_surface.rs +++ b/src/ifs/wl_surface.rs @@ -629,7 +629,7 @@ impl Node for WlSurface { self.xdg.get().map(|x| x.create_split(split)); } - fn move_focus(&self, seat: &Rc, direction: Direction) { + fn move_focus(self: Rc, seat: &Rc, direction: Direction) { let xdg = match self.xdg.get() { Some(x) => x, _ => return, diff --git a/src/text.rs b/src/text.rs index f33b8632..968b8d0a 100644 --- a/src/text.rs +++ b/src/text.rs @@ -47,12 +47,14 @@ pub fn render( }; let fd = FontDescription::from_string(font); let layout = Layout::new(&pctx); - layout.set_width(width * pango::SCALE); + layout.set_width((width - 2).max(0) * pango::SCALE); layout.set_ellipsize(EllipsizeMode::End); layout.set_font_description(Some(&fd)); layout.set_text(text); + let font_height = layout.pixel_size().1; cctx.set_operator(Operator::Source); cctx.set_source_rgba(color.r as _, color.g as _, color.b as _, color.a as _); + cctx.move_to(1.0, ((height - font_height) / 2) as f64); pangocairo::show_layout(&cctx, &layout); let mut texture = None; let _ = image.with_data(|d| unsafe { diff --git a/src/theme.rs b/src/theme.rs index 9ba5c7e4..bb0a189c 100644 --- a/src/theme.rs +++ b/src/theme.rs @@ -15,6 +15,13 @@ impl Color { b: 0.0, a: 1.0, }; + + pub const GREY: Self = Self { + r: 0.8, + g: 0.8, + b: 0.8, + a: 1.0, + }; } fn to_f32(c: u8) -> f32 { diff --git a/src/tree/container.rs b/src/tree/container.rs index 2e8f089f..0e88803f 100644 --- a/src/tree/container.rs +++ b/src/tree/container.rs @@ -14,7 +14,7 @@ use i4config::{Axis, Direction}; use std::cell::{Cell, RefCell}; use std::fmt::{Debug, Formatter}; use std::mem; -use std::ops::{Deref, DerefMut}; +use std::ops::{Deref, DerefMut, Sub}; use std::rc::Rc; use crate::backend::KeyState; @@ -336,15 +336,16 @@ impl ContainerNode { let new_content_size = self .width .get() - .saturating_sub((nc - 1) as i32 * border_width); + .sub((nc - 1) as i32 * border_width) + .max(0); self.content_width.set(new_content_size); self.content_height - .set(self.height.get().saturating_sub(title_height + 1)); + .set(self.height.get().sub(title_height + 1).max(0)); } ContainerSplit::Vertical => { - let new_content_size = self.height.get().saturating_sub( + let new_content_size = self.height.get().sub( title_height + 1 + (nc - 1) as i32 * (border_width + title_height + 1), - ); + ).max(0); self.content_height.set(new_content_size); self.content_width.set(self.width.get()); } @@ -448,7 +449,7 @@ impl ContainerNode { title.push_str("["); for (i, c) in self.children.iter().enumerate() { if i > 0 { - title.push_str(" "); + title.push_str(", "); } title.push_str(c.title.borrow_mut().deref()); } @@ -470,7 +471,8 @@ impl ContainerNode { for c in self.children.iter() { c.title_texture.set(None); let title = c.title.borrow_mut(); - if title.is_empty() { + let body = c.body.get(); + if title.is_empty() || th == 0 || body.width() == 0 { continue; } let ctx = match self.state.render_ctx.get() { @@ -478,7 +480,7 @@ impl ContainerNode { _ => continue, }; let texture = - match text::render(&ctx, c.body.get().width(), th, &font, &title, Color::RED) { + match text::render(&ctx, body.width(), th, &font, &title, Color::GREY) { Ok(t) => t, Err(e) => { log::error!("Could not render title {}: {}", title, ErrorFmt(e)); @@ -541,6 +543,16 @@ impl Node for ContainerNode { self.seat_state.destroy_node(self); } + fn visit(self: Rc, visitor: &mut dyn NodeVisitor) { + visitor.visit_container(&self); + } + + fn visit_children(&self, visitor: &mut dyn NodeVisitor) { + for child in self.children.iter() { + child.node.clone().visit(visitor); + } + } + fn child_title_changed(self: Rc, child: &dyn Node, title: &str) { let child = match self.child_nodes.borrow_mut().get(&child.id()) { Some(cn) => cn.to_ref(), @@ -557,26 +569,28 @@ impl Node for ContainerNode { self.update_title(); } - fn focus_parent(&self, seat: &Rc) { - self.parent.get().focus_self(seat); + fn get_split(&self) -> Option { + Some(self.split.get()) } - fn active_changed(&self, active: bool) { - self.parent.get().child_active_changed(self, active); + fn set_split(self: Rc, split: ContainerSplit) { + if self.split.replace(split) != split { + self.update_content_size(); + self.schedule_layout(); + self.update_title(); + } } fn focus_self(self: Rc, seat: &Rc) { seat.focus_node(self); } - fn get_split(&self) -> Option { - Some(self.split.get()) - } - - fn set_split(self: Rc, split: ContainerSplit) { - self.split.set(split); - self.update_content_size(); - self.schedule_layout(); + fn move_focus(self: Rc, seat: &Rc, direction: Direction) { + if direction == Direction::Down { + self.do_focus(seat, direction); + return; + } + self.parent.get().move_focus_from_child(seat, &*self, direction); } fn do_focus(self: Rc, seat: &Rc, direction: Direction) { @@ -643,6 +657,10 @@ impl Node for ContainerNode { .unwrap() } + fn active_changed(&self, active: bool) { + self.parent.get().child_active_changed(self, active); + } + fn button(self: Rc, seat: &Rc, button: u32, state: KeyState) { if button != BTN_LEFT { return; @@ -715,6 +733,10 @@ impl Node for ContainerNode { } } + fn focus_parent(&self, seat: &Rc) { + self.parent.get().focus_self(seat); + } + fn find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { let mut recurse = |content: Rect, child: NodeRef| { if content.contains(x, y) { @@ -802,6 +824,14 @@ impl Node for ContainerNode { } } + fn child_active_changed(&self, child: &dyn Node, active: bool) { + let node = match self.child_nodes.borrow_mut().get(&child.id()) { + Some(l) => l.to_ref(), + None => return, + }; + node.active.set(active); + } + fn enter(self: Rc, seat: &Rc, x: Fixed, y: Fixed) { self.pointer_move(seat, x.round_down(), y.round_down()); } @@ -825,14 +855,6 @@ impl Node for ContainerNode { self.pointer_move(seat, x.round_down(), y.round_down()); } - fn child_active_changed(&self, child: &dyn Node, active: bool) { - let node = match self.child_nodes.borrow_mut().get(&child.id()) { - Some(l) => l.to_ref(), - None => return, - }; - node.active.set(active); - } - fn render(&self, renderer: &mut Renderer, x: i32, y: i32) { renderer.render_container(self, x, y); } @@ -868,14 +890,4 @@ impl Node for ContainerNode { } self.workspace.set(ws.clone()); } - - fn visit(self: Rc, visitor: &mut dyn NodeVisitor) { - visitor.visit_container(&self); - } - - fn visit_children(&self, visitor: &mut dyn NodeVisitor) { - for child in self.children.iter() { - child.node.clone().visit(visitor); - } - } } diff --git a/src/tree/mod.rs b/src/tree/mod.rs index 4faad60f..e774644c 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs @@ -105,7 +105,7 @@ pub trait Node { let _ = direction; } - fn move_focus(&self, seat: &Rc, direction: Direction) { + fn move_focus(self: Rc, seat: &Rc, direction: Direction) { let _ = seat; let _ = direction; }