Saltar al contenido

Monitores y multi-pantalla

Cómo se consulta la lista de monitores, qué es el área de trabajo frente al área total, y el algoritmo de tres pasos para colocar una ventana donde el usuario espera y no fuera de la pantalla.

Consultar los monitores

Rust
// Todos los conectados ahora mismo.for m in app.available_monitors()? {    println!("{:?} · {:?} en {:?}, escala {}",        m.name(), m.size(), m.position(), m.scale_factor());}// El principal, y el que contiene una ventana concreta.let principal = app.primary_monitor()?;let actual = win.current_monitor()?;   // None si la ventana no está en ninguno

Ese None del último caso no es teórico: una ventana puede no estar en ningún monitor, precisamente cuando se ha restaurado en una posición que ya no existe. Tratarlo es la mitad de la solución.

Cada monitor da cuatro cosas: un nombre, su tamaño, su posición en el escritorio virtual —en píxeles físicos, como avisaba el nivel 11.2— y su factor de escala, que puede ser distinto para cada uno.

Área total y área de trabajo

Es la distinción que más se olvida y produce ventanas debajo de la barra de tareas.

La regla es corta: para colocar ventanas, área de trabajo; para ocupar la pantalla, área total.

La comprobación que hay que escribir

El algoritmo de tres pasos que evita la ventana invisible:

Un margen que conviene: en vez de exigir que la ventana quepa entera, basta con comprobar que una franja suficiente de su barra de título queda dentro del área de trabajo. Es lo que hacen los gestores de ventanas del sistema, y evita descartar posiciones perfectamente usables donde el usuario había dejado la ventana medio fuera a propósito.

Colocar en un monitor concreto

Cuando quieres abrir una ventana en un monitor determinado —el que tiene el cursor, el secundario, el mismo que otra ventana— la forma correcta es preguntar y no calcular:

Rust
// Centrar en el monitor donde está el cursor, sin aritmética de escalado.if let Some(m) = app.monitor_from_point(x, y)? {    let area = m.work_area();    let tam = win.outer_size()?;    let pos = tauri::PhysicalPosition::new(        area.position.x + (area.size.width as i32 - tam.width as i32) / 2,        area.position.y + (area.size.height as i32 - tam.height as i32) / 2,    );    win.set_position(pos)?;}

Todo en físicos, porque las coordenadas del escritorio virtual lo son. Y usando el área de trabajo, no el tamaño total.

Para el caso más común —centrar en el monitor actual— no hace falta nada de esto: hay una llamada que lo hace, y también la clave de configuración del nivel 7.2. El código de arriba es para cuando el monitor no es el actual.