feat(shuma): cajón de resultados del shell — desplegable desde el pie
Fase 3c: el shell muestra la salida de los comandos en un cajón que se despliega hacia arriba sobre el escritorio. carmen — la ventana del shell deja de tener un alto fijo: `render_loc` la ancla al pie de la salida y la coloca por su **tamaño real**, así puede crecer hacia arriba. La franja reservada sigue siendo la barra (40 px); el cajón, al abrirse, se solapa sobre las teseladas sin re-teselar. `render_loc` toma ahora el alto de la salida. shuma-shell — un clic en el estado alterna `drawer_open`: la ventana crece (`Window::resize`, que GPUI 0.2 expone) a barra + cajón, o vuelve a sólo barra. El cajón reusa `render_run` para pintar los últimos comandos y su salida, con scroll. `render_launcher` pasa a una columna: cajón opcional arriba, barra abajo. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -152,6 +152,7 @@ impl DrmState {
|
||||
if self.pending_flip {
|
||||
return; // aún esperamos el VBlank del cuadro anterior
|
||||
}
|
||||
let output_h = self.app.output_size.1;
|
||||
|
||||
// Paso 1 · refresca los búferes del marco de cada ventana — su
|
||||
// tamaño (sigue al contenido) y su color (según el foco). Cada
|
||||
@@ -160,7 +161,7 @@ impl DrmState {
|
||||
if !w.visible || w.is_shell {
|
||||
continue; // el shell no lleva marco
|
||||
}
|
||||
let (x, y) = crate::render_loc(w);
|
||||
let (x, y) = crate::render_loc(w, output_h);
|
||||
let (sw, sh) = crate::surface_px_size(w).unwrap_or(w.size);
|
||||
let color = if w.focused { BORDER_FOCUS } else { BORDER_NORMAL };
|
||||
let rects = border_rects(x, y, sw, sh);
|
||||
@@ -216,7 +217,7 @@ impl DrmState {
|
||||
let mut shown: Vec<_> = self.app.windows.iter().filter(|w| w.visible).collect();
|
||||
shown.sort_by_key(|w| (!w.is_shell, !w.floating));
|
||||
for w in &shown {
|
||||
let (x, y) = crate::render_loc(w);
|
||||
let (x, y) = crate::render_loc(w, output_h);
|
||||
let (sw, sh) = crate::surface_px_size(w).unwrap_or(w.size);
|
||||
// El marco, encima de la propia superficie de la ventana
|
||||
// — el shell no lleva.
|
||||
@@ -507,7 +508,7 @@ impl DrmState {
|
||||
let hit = self.window_at(x, y);
|
||||
let focus = hit.map(|i| {
|
||||
let w = &self.app.windows[i];
|
||||
let (lx, ly) = crate::render_loc(w);
|
||||
let (lx, ly) = crate::render_loc(w, self.app.output_size.1);
|
||||
(
|
||||
w.surface.clone(),
|
||||
Point::<f64, Logical>::from((lx as f64, ly as f64)),
|
||||
@@ -593,9 +594,10 @@ impl DrmState {
|
||||
let w = &self.app.windows[i];
|
||||
(!w.is_shell, !w.floating)
|
||||
});
|
||||
let output_h = self.app.output_size.1;
|
||||
idx.into_iter().find(|&i| {
|
||||
let w = &self.app.windows[i];
|
||||
let (lx, ly) = crate::render_loc(w);
|
||||
let (lx, ly) = crate::render_loc(w, output_h);
|
||||
let (sw, sh) = crate::surface_px_size(w).unwrap_or(w.size);
|
||||
x >= lx as f64 && y >= ly as f64 && x < (lx + sw) as f64 && y < (ly + sh) as f64
|
||||
})
|
||||
|
||||
@@ -676,11 +676,16 @@ fn send_frames_surface_tree(surface: &WlSurface, time: u32) {
|
||||
// Bucle principal
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/// Dónde pintar una ventana: su celda asignada, pero si el cliente
|
||||
/// presenta una superficie más pequeña que la celda (p. ej. un terminal
|
||||
/// que redondea su tamaño a celdas de texto enteras), se centra en el
|
||||
/// hueco sobrante en vez de dejarlo todo a un lado.
|
||||
fn render_loc(w: &ManagedWindow) -> (i32, i32) {
|
||||
/// Dónde pintar una ventana. La del shell se ancla al pie de la salida
|
||||
/// y crece hacia arriba (su cajón de resultados se despliega sobre las
|
||||
/// ventanas). Una ventana normal va en su celda; si el cliente presenta
|
||||
/// una superficie más pequeña que la celda (p. ej. un terminal que
|
||||
/// redondea su tamaño a celdas de texto), se centra en el hueco.
|
||||
fn render_loc(w: &ManagedWindow, output_h: i32) -> (i32, i32) {
|
||||
if w.is_shell {
|
||||
let h = surface_px_size(w).map(|(_, h)| h).unwrap_or(SHELL_DOCK_HEIGHT);
|
||||
return (0, output_h - h);
|
||||
}
|
||||
match with_renderer_surface_state(&w.surface, |s| s.surface_size()) {
|
||||
Some(Some(size)) => {
|
||||
let dx = ((w.size.0 - size.w) / 2).max(0);
|
||||
@@ -1082,6 +1087,7 @@ fn run_winit() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// (índice 0 = encima): el shell primero —va sobre todo—, luego
|
||||
// las flotantes, luego las teseladas. `sort_by_key` es estable:
|
||||
// dentro de cada grupo se respeta el orden de apertura.
|
||||
let output_h = state.output_size.1;
|
||||
let mut shown: Vec<&ManagedWindow> =
|
||||
state.windows.iter().filter(|w| w.visible).collect();
|
||||
shown.sort_by_key(|w| (!w.is_shell, !w.floating));
|
||||
@@ -1091,7 +1097,7 @@ fn run_winit() -> Result<(), Box<dyn std::error::Error>> {
|
||||
render_elements_from_surface_tree(
|
||||
renderer,
|
||||
&w.surface,
|
||||
render_loc(w),
|
||||
render_loc(w, output_h),
|
||||
1.0,
|
||||
1.0,
|
||||
Kind::Unspecified,
|
||||
|
||||
Reference in New Issue
Block a user