From 71952ab90b8b638b84a65548b2a657d8a50e4f0f Mon Sep 17 00:00:00 2001 From: Bjorn Blomberg Date: Wed, 15 Jul 2026 19:19:21 +0200 Subject: [PATCH] =?UTF-8?q?Polish=20window=20frames:=20inset=20title=20chi?= =?UTF-8?q?p,=20=E2=9C=95=20close=20button,=20drop=20shadow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Title rendered as a chip inset in the border (┤ titel ├), accent colored when focused, dimmed when not - Close button restyled to ┤✕├ matching the frame - Subtle drop shadow below/right of windows (darkened cells, content underneath stays visible; skipped when a background image is active) Co-Authored-By: Claude Fable 5 --- src/render.rs | 48 +++++++++++++++++++++++++++++++++++++++++++++--- src/theme.rs | 13 ++++++++++--- 2 files changed, 55 insertions(+), 6 deletions(-) diff --git a/src/render.rs b/src/render.rs index 81d7756..2f5b92b 100644 --- a/src/render.rs +++ b/src/render.rs @@ -216,6 +216,12 @@ fn render_window( WindowContent::PopupDialog { .. } => " TUI-WM ".to_string(), }; + // Diskret skugga nedanför/till höger om fönstret (inte när en + // bakgrundsbild används — då ska skrivbordet synas igenom). + if outer_bg != Color::Reset { + render_shadow(frame, full_rect); + } + frame.render_widget(Clear, full_rect); // Ramzonen målas i skrivbordets färg — annars fylls även hörncellerna // utanför de rundade hörnen med fönstrets bakgrund och rutan ser @@ -233,16 +239,22 @@ fn render_window( Block::default().style(Style::default().bg(content_bg)), inner_rect, ); + // Titeln renderas som ett "chip" infällt i ramen: ┤ titel ├ + let title_line = Line::from(vec![ + Span::styled("┤", border_style), + Span::styled(title_text.clone(), theme::window_title(is_focused)), + Span::styled("├", border_style), + ]); frame.render_widget( Block::default() - .title(Span::styled(&title_text, theme::window_title())) + .title(title_line) .borders(Borders::ALL) .border_type(BorderType::Rounded) .border_style(border_style), full_rect, ); - // Stäng-knapp [X] + // Stäng-knapp: ┤✕├ infälld i ramen (✕ U+2715 är ett smalt textglyf) let cb = window.close_btn_rect(); if cb.x + 3 <= full_rect.x + full_rect.width { let close_hov = hovered_close == Some(window.id); @@ -251,7 +263,12 @@ fn render_window( } else { Style::default().fg(theme::DANGER) }; - frame.render_widget(Paragraph::new(Span::styled("[X]", close_style)), cb); + let close_line = Line::from(vec![ + Span::styled("┤", border_style), + Span::styled("✕", close_style), + Span::styled("├", border_style), + ]); + frame.render_widget(Paragraph::new(close_line), cb); } // Resize-hints – bara om fönstret är resizable @@ -309,6 +326,31 @@ fn render_window( } } +/// Ritar en skugga: raden under och kolumnen till höger om fönstret får +/// mörkare bakgrund + dämpad text, så fönstren ser ut att sväva över +/// skrivbordet. Muterar cellerna direkt så att underliggande innehåll +/// (andra fönster/skrivbordet) syns kvar — bara mörkare. +fn render_shadow(frame: &mut Frame, rect: Rect) { + let area = frame.area(); + let buf = frame.buffer_mut(); + let mut shade = |x: u16, y: u16| { + if x < area.width && y < area.height { + if let Some(cell) = buf.cell_mut((x, y)) { + cell.set_bg(theme::SHADOW_BG); + cell.modifier.insert(Modifier::DIM); + } + } + }; + // Rad under fönstret (förskjuten ett steg åt höger) + for x in (rect.x + 1)..(rect.x + rect.width + 1) { + shade(x, rect.y + rect.height); + } + // Kolumn till höger om fönstret + for y in (rect.y + 1)..(rect.y + rect.height) { + shade(rect.x + rect.width, y); + } +} + fn render_popup_dialog( frame: &mut Frame, window: &FloatingWindow, diff --git a/src/theme.rs b/src/theme.rs index 3538637..b7657cb 100644 --- a/src/theme.rs +++ b/src/theme.rs @@ -64,7 +64,14 @@ pub fn panel_item() -> Style { Style::default().fg(PANEL_TEXT).bg(PANEL_BG) } -/// Fönstertitel. -pub fn window_title() -> Style { - Style::default().fg(TEXT).add_modifier(Modifier::BOLD) +/// Fönstertitel — accentfärgad när fönstret har fokus. +pub fn window_title(focused: bool) -> Style { + if focused { + Style::default().fg(ACCENT).add_modifier(Modifier::BOLD) + } else { + Style::default().fg(HINT) + } } + +/// Bakgrundsfärg för fönsterskuggan (mörkare än skrivbordet). +pub const SHADOW_BG: Color = Color::Indexed(233);