feat(mirada-compositor): centrar la ventana en su celda si el cliente no la llena

Un cliente que presenta una superficie más pequeña que su celda (p. ej.
un terminal que redondea a celdas de texto enteras) dejaba el hueco todo
a un lado. Ahora ManagedWindow recuerda el tamaño de la celda y
render_loc() centra la superficie en el sobrante. Lo usan los dos
backends (winit y DRM).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
sergio
2026-05-21 03:12:44 +00:00
parent c07356d8bc
commit 5230d42b11
2 changed files with 26 additions and 4 deletions
@@ -92,7 +92,7 @@ impl DrmState {
render_elements_from_surface_tree(
&mut self.renderer,
&w.surface,
w.loc,
crate::render_loc(w),
1.0,
1.0,
Kind::Unspecified,
+25 -3
View File
@@ -26,7 +26,9 @@ use smithay::backend::renderer::element::surface::{
};
use smithay::backend::renderer::element::Kind;
use smithay::backend::renderer::gles::GlesRenderer;
use smithay::backend::renderer::utils::{draw_render_elements, on_commit_buffer_handler};
use smithay::backend::renderer::utils::{
draw_render_elements, on_commit_buffer_handler, with_renderer_surface_state,
};
use smithay::backend::renderer::{Color32F, Frame, Renderer};
use smithay::backend::winit::{self, WinitEvent};
use smithay::input::keyboard::{xkb, FilterResult, KeyboardHandle, Keysym, ModifiersState};
@@ -86,8 +88,11 @@ struct ManagedWindow {
id: u64,
toplevel: ToplevelSurface,
surface: WlSurface,
/// Esquina superior-izquierda en píxeles, según el Cerebro.
/// Esquina superior-izquierda de la celda asignada, según el Cerebro.
loc: (i32, i32),
/// Tamaño de la celda asignada — para centrar la ventana si el
/// cliente presenta una superficie más pequeña.
size: (i32, i32),
visible: bool,
/// `true` si flota: se compone por encima de las teseladas.
floating: bool,
@@ -182,6 +187,7 @@ impl App {
BodyOp::Configure { id, rect, visible, floating, fullscreen } => {
if let Some(w) = self.windows.iter_mut().find(|w| w.id == id) {
w.loc = (rect.x, rect.y);
w.size = (rect.w, rect.h);
w.visible = visible;
w.floating = floating;
w.toplevel.with_pending_state(|s| {
@@ -258,6 +264,7 @@ impl App {
toplevel,
surface,
loc: (0, 0),
size: (0, 0),
visible: false,
floating: false,
});
@@ -512,6 +519,21 @@ 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) {
match with_renderer_surface_state(&w.surface, |s| s.surface_size()) {
Some(Some(size)) => {
let dx = ((w.size.0 - size.w) / 2).max(0);
let dy = ((w.size.1 - size.h) / 2).max(0);
(w.loc.0 + dx, w.loc.1 + dy)
}
_ => w.loc,
}
}
/// Carga las reglas de ventana del usuario, o ninguna si no hay archivo.
fn load_user_rules() -> Rules {
match Rules::default_path() {
@@ -815,7 +837,7 @@ fn run_winit() -> Result<(), Box<dyn std::error::Error>> {
render_elements_from_surface_tree(
renderer,
&w.surface,
w.loc,
render_loc(w),
1.0,
1.0,
Kind::Unspecified,