2025-06-29 22:39:17 -05:00
|
|
|
// client/src/output/display.rs
|
|
|
|
|
|
|
|
|
|
use gtk::prelude::ListModelExt;
|
|
|
|
|
use gtk::prelude::*;
|
|
|
|
|
use gtk::gdk;
|
|
|
|
|
use tracing::debug;
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
|
pub struct MonitorInfo {
|
|
|
|
|
pub geometry: gdk::Rectangle,
|
|
|
|
|
pub scale_factor: i32,
|
|
|
|
|
pub is_internal: bool,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Enumerate monitors sorted by our desired priority.
|
|
|
|
|
pub fn enumerate_monitors() -> Vec<MonitorInfo> {
|
|
|
|
|
let Some(display) = gdk::Display::default() else {
|
2025-06-30 15:45:37 -05:00
|
|
|
tracing::warn!("⚠️ no GDK display - falling back to single-monitor 0,0");
|
2025-06-29 22:39:17 -05:00
|
|
|
return vec![MonitorInfo {
|
|
|
|
|
geometry: gdk::Rectangle::new(0, 0, 1920, 1080),
|
|
|
|
|
scale_factor: 1,
|
|
|
|
|
is_internal: false,
|
|
|
|
|
}];
|
|
|
|
|
};
|
|
|
|
|
let model = display.monitors(); // gio::ListModel
|
|
|
|
|
|
|
|
|
|
let mut list: Vec<_> = (0..model.n_items())
|
|
|
|
|
.filter_map(|i| model.item(i))
|
|
|
|
|
.filter_map(|obj| obj.downcast::<gdk::Monitor>().ok())
|
|
|
|
|
.map(|m| {
|
|
|
|
|
// -------- internal vs external ----------------------------------
|
|
|
|
|
let connector = m.connector().unwrap_or_default(); // e.g. "eDP-1"
|
|
|
|
|
let is_internal = connector.starts_with("eDP")
|
|
|
|
|
|| connector.starts_with("LVDS")
|
|
|
|
|
|| connector.starts_with("DSI")
|
|
|
|
|
|| connector.to_ascii_lowercase().contains("internal");
|
|
|
|
|
|
|
|
|
|
// -------- geometry / scale --------------------------------------
|
|
|
|
|
let geometry = m.geometry();
|
|
|
|
|
let scale_factor = m.scale_factor();
|
|
|
|
|
|
|
|
|
|
debug!(
|
|
|
|
|
"🖥️ monitor: {:?}, connector={:?}, geom={:?}, scale={}",
|
|
|
|
|
m.model(), connector, geometry, scale_factor
|
|
|
|
|
);
|
|
|
|
|
MonitorInfo { geometry, scale_factor, is_internal }
|
|
|
|
|
})
|
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
|
|
// external first, built-in last
|
|
|
|
|
list.sort_by_key(|m| m.is_internal);
|
|
|
|
|
debug!("🖥️ sorted monitors = {:?}", list);
|
|
|
|
|
list
|
|
|
|
|
}
|