use crate::model::config::{Display, DisplayMode}; use anyhow::Result; use displayz::{query_displays, DisplaySet}; use tauri::{AppHandle, Listener}; #[cfg(target_os = "windows")] #[derive(Clone)] pub struct DisplayInfo { pub primary: String, pub set: Option } impl Default for DisplayInfo { fn default() -> Self { DisplayInfo { primary: "default".to_owned(), set: query_displays().ok() } } } impl Default for Display { fn default() -> Self { Display { target: "default".to_owned(), rez: (1080, 1920), mode: DisplayMode::Borderless, rotation: 0, frequency: 60, borderless_fullscreen: true, } } } #[cfg(target_os = "windows")] impl Display { pub fn activate(&self, app: AppHandle) { let display = self.clone(); tauri::async_runtime::spawn(async move { let info = display.line_up()?; if let Some(info) = info { app.listen("launch-end", move |_| { if let Err(e) = Self::clean_up(&info) { log::error!("Error cleaning up display: {:?}", e); } }); } Ok::<(), anyhow::Error>(()) }); } fn line_up(&self) -> Result> { use anyhow::anyhow; use displayz::{query_displays, Orientation, Resolution, Frequency}; if self.target == "default" { log::debug!("prepare display: skip"); return Ok(None); } let display_set = query_displays()?; let primary = display_set .displays() .find(|display| display.is_primary()) .ok_or_else(|| anyhow!("Primary display not found"))?; let target = display_set .displays() .find(|display| display.name() == self.target) .ok_or_else(|| anyhow!("Display {} not found", self.target))?; target.set_primary()?; let settings = target.settings() .as_ref() .ok_or_else(|| anyhow!("Unable to query display settings"))?; let res = DisplayInfo { primary: primary.name().to_owned(), set: Some(display_set.clone()) }; if self.rotation == 90 || self.rotation == 270 { let rez = settings.borrow_mut().resolution; settings.borrow_mut().orientation = if self.rotation == 90 { Orientation::PortraitFlipped } else { Orientation::Portrait }; if rez.height < rez.width { settings.borrow_mut().resolution = Resolution::new(rez.height, rez.width); } } let frequency: u32 = self.frequency .try_into() .map_err(|e| anyhow!("Invalid display frequency: {}", e))?; let width: u32 = self.rez.0 .try_into() .map_err(|e| anyhow!("Invalid display width: {}", e))?; let height: u32 = self.rez.1 .try_into() .map_err(|e| anyhow!("Invalid display height: {}", e))?; settings.borrow_mut().frequency = Frequency::new(frequency); if self.borderless_fullscreen && self.mode == DisplayMode::Borderless { settings.borrow_mut().resolution = Resolution::new(width, height); } display_set.apply()?; displayz::refresh()?; log::debug!("prepare display: done"); Ok(Some(res)) } fn clean_up(info: &DisplayInfo) -> Result<()> { use anyhow::anyhow; let display_set = info.set.as_ref() .ok_or_else(|| anyhow!("Unable to clean up displays: no display set"))?; let primary = display_set .displays() .find(|display| display.name() == info.primary) .ok_or_else(|| anyhow!("Display {} not found", info.primary))?; primary.set_primary()?; display_set.apply()?; displayz::refresh()?; log::debug!("undo display: done"); Ok(()) } }