use crate::{model::{misc::Game, profile::{Display, DisplayMode}}, util::bool_to_01}; use anyhow::Result; use displayz::{query_displays, DisplaySet}; use ini::Ini; use tauri::{AppHandle, Listener}; #[derive(Clone)] pub struct DisplayInfo { pub primary: Option, pub set: Option, } impl Default for DisplayInfo { fn default() -> Self { DisplayInfo { primary: None, set: query_displays().ok(), } } } impl Display { pub fn wait_for_exit(app: AppHandle, info: DisplayInfo) { log::debug!("display: waiting"); tauri::async_runtime::spawn(async move { app.listen("launch-end", move |_| { if let Err(e) = Self::clean_up(&info) { log::error!("error cleaning up display: {:?}", e); } }); }); } pub fn prepare(&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))?; if !self.dont_switch_primary { target.set_primary()?; } let settings = target.settings() .as_ref() .ok_or_else(|| anyhow!("Unable to query display settings"))?; let res = DisplayInfo { primary: if self.dont_switch_primary { None } else { Some(primary.name().to_owned()) }, set: Some(display_set.clone()), }; if let Some(rotation) = self.rotation { let rez = settings.borrow_mut().resolution; settings.borrow_mut().orientation = match rotation { 0 => Orientation::Landscape, 90 => Orientation::PortraitFlipped, 180 => Orientation::LandscapeFlipped, 270 => Orientation::Portrait, _ => panic!("Invalid display rotation") }; if rez.height < rez.width { if rotation == 90 || rotation == 270 { settings.borrow_mut().resolution = Resolution::new(rez.height, rez.width); } } else { if rotation == 0 || rotation == 180 { 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().map_err( |_| anyhow!("The selected monitor has been disconnected or doesn't support the chosen display mode") )?; displayz::refresh()?; log::debug!("prepare display: done"); Ok(Some(res)) } pub fn line_up(&self, game: Game, ini: &mut Ini) { if game == Game::Chunithm { let autism = self.monitor_index_override.unwrap_or(0).to_string(); ini.with_section(Some("gfx")) .set("enable", "1") .set("windowed", bool_to_01(self.mode != DisplayMode::Fullscreen)) .set("framed", bool_to_01(self.mode == DisplayMode::Window)) .set("monitor", if self.dont_switch_primary { &autism } else { "0" }); ini.with_section(Some("system")) .set("dipsw2", bool_to_01(self.frequency == 60)) .set("dipsw3", bool_to_01(self.frequency == 60)); } } pub 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"))?; if let Some(info_primary) = &info.primary { 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(()) } }