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>
5230d42b112a5fc846d3108275b38188bd28e1db · por sergio · 2026-05-21T03:12:44Z (hace 5 meses) · padre c07356d8b · ver el árbol en este commit
Delta semántico · 6
crates/apps/mirada-compositor/src/drm_backend.rs
crates/apps/mirada-compositor/src/main.rs
diff --git a/crates/apps/mirada-compositor/src/drm_backend.rs b/crates/apps/mirada-compositor/src/drm_backend.rs
index fdbd593..e0bc467 100644
--- a/crates/apps/mirada-compositor/src/drm_backend.rs
+++ b/crates/apps/mirada-compositor/src/drm_backend.rs
@@ -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,
diff --git a/crates/apps/mirada-compositor/src/main.rs b/crates/apps/mirada-compositor/src/main.rs
index 9340ea3..d2c11f1 100644
--- a/crates/apps/mirada-compositor/src/main.rs
+++ b/crates/apps/mirada-compositor/src/main.rs
@@ -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,