diff --git a/libs/scrap/src/common/dxgi.rs b/libs/scrap/src/common/dxgi.rs index 3bf1783a8..a49ea2768 100644 --- a/libs/scrap/src/common/dxgi.rs +++ b/libs/scrap/src/common/dxgi.rs @@ -111,16 +111,23 @@ impl Display { let tmp = Self::all_().unwrap_or(Default::default()); if tmp.is_empty() { println!("Display got from gdi"); - return Ok(dxgi::Displays::get_from_gdi() - .drain(..) - .map(Display) - .collect::>()); + return Ok(Self::displays_from_dxgi_displays( + dxgi::Displays::get_from_gdi().drain(..), + )); } Ok(tmp) } + #[inline] + pub fn displays_from_dxgi_displays(displays: I) -> Vec + where + I: Iterator, + { + displays.map(Display).collect::>() + } + fn all_() -> io::Result> { - Ok(dxgi::Displays::new()?.map(Display).collect::>()) + Ok(Self::displays_from_dxgi_displays(dxgi::Displays::new()?)) } pub fn width(&self) -> usize { diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index f4ef1434e..7cad8df67 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -1098,7 +1098,7 @@ pub fn main_get_main_display() -> SyncReturn { #[cfg(not(target_os = "ios"))] let mut display_info = "".to_owned(); #[cfg(not(target_os = "ios"))] - if let Ok(displays) = crate::display_service::try_get_displays() { + if let Ok(displays) = crate::display_service::try_get_displays(false) { // to-do: Need to detect current display index. if let Some(display) = displays.iter().next() { display_info = serde_json::to_string(&HashMap::from([ @@ -1117,7 +1117,7 @@ pub fn main_get_displays() -> SyncReturn { #[cfg(not(target_os = "ios"))] let mut display_info = "".to_owned(); #[cfg(not(target_os = "ios"))] - if let Ok(displays) = crate::display_service::try_get_displays() { + if let Ok(displays) = crate::display_service::try_get_displays(false) { let displays = displays .iter() .map(|d| { diff --git a/src/server/connection.rs b/src/server/connection.rs index b0fd19891..ec518adfd 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -1165,7 +1165,7 @@ impl Connection { #[cfg(not(any(target_os = "android", target_os = "ios")))] { pi.resolutions = Some(SupportedResolutions { - resolutions: display_service::try_get_displays() + resolutions: display_service::try_get_displays(true) .map(|displays| { displays .get(self.display_idx) @@ -2366,7 +2366,7 @@ impl Connection { #[cfg(not(any(target_os = "android", target_os = "ios")))] fn change_resolution(&mut self, r: &Resolution) { if self.keyboard { - if let Ok(displays) = display_service::try_get_displays() { + if let Ok(displays) = display_service::try_get_displays(true) { if let Some(display) = displays.get(self.display_idx) { let name = display.name(); #[cfg(all(windows, feature = "virtual_display_driver"))] diff --git a/src/server/display_service.rs b/src/server/display_service.rs index a9a49818c..25cb6e0a7 100644 --- a/src/server/display_service.rs +++ b/src/server/display_service.rs @@ -180,7 +180,7 @@ fn displays_to_msg(displays: Vec) -> Message { } fn check_get_displays_changed_msg() -> Option { - check_update_displays(&try_get_displays().ok()?); + check_update_displays(&try_get_displays(true).ok()?); let displays = SYNC_DISPLAYS.lock().unwrap().get_update_sync_displays()?; Some(displays_to_msg(displays)) } @@ -292,7 +292,7 @@ pub async fn update_get_sync_displays() -> ResultType> { return super::wayland::get_displays().await; } } - check_update_displays(&try_get_displays()?); + check_update_displays(&try_get_displays(true)?); Ok(SYNC_DISPLAYS.lock().unwrap().displays.clone()) } @@ -308,7 +308,9 @@ pub fn get_primary() -> usize { } } - try_get_displays().map(|d| get_primary_2(&d)).unwrap_or(0) + try_get_displays(false) + .map(|d| get_primary_2(&d)) + .unwrap_or(0) } #[inline] @@ -343,20 +345,41 @@ fn no_displays(displays: &Vec) -> bool { #[inline] #[cfg(not(all(windows, feature = "virtual_display_driver")))] -pub fn try_get_displays() -> ResultType> { - Ok(Display::all()?) +pub fn try_get_displays(_order: bool) -> ResultType> { + Ok(get_displays(_order)?) } #[cfg(all(windows, feature = "virtual_display_driver"))] -pub fn try_get_displays() -> ResultType> { - let mut displays = Display::all()?; +pub fn try_get_displays(order: bool) -> ResultType> { + let mut displays = get_displays(order)?; if crate::platform::is_installed() && no_displays(&displays) { log::debug!("no displays, create virtual display"); if let Err(e) = virtual_display_manager::plug_in_headless() { log::error!("plug in headless failed {}", e); } else { - displays = Display::all()?; + displays = get_displays(order)?; } } Ok(displays) } + +// Note: Do not use `Display::all()` to get displays. +// Use `get_displays()` instead. + +#[cfg(not(windows))] +pub fn get_displays(_order: bool) -> ResultType> { + Ok(Display::all()?) +} + +// get_from_gdi() returns the displays in the same order of the windows display settings. +// dxgi does not guarantee the order of displays. +#[cfg(windows)] +pub fn get_displays(order: bool) -> ResultType> { + if !order { + Ok(Display::all()?) + } else { + Ok(Display::displays_from_dxgi_displays( + scrap::dxgi::Displays::get_from_gdi().drain(..), + )) + } +} diff --git a/src/server/portable_service.rs b/src/server/portable_service.rs index 51d665d0a..3c52c1d7a 100644 --- a/src/server/portable_service.rs +++ b/src/server/portable_service.rs @@ -317,7 +317,7 @@ pub mod server { let current_display = (*para).current_display; let timeout_ms = (*para).timeout_ms; if c.is_none() { - let Ok(mut displays) = display_service::try_get_displays() else { + let Ok(mut displays) = display_service::try_get_displays(true) else { log::error!("Failed to get displays"); *EXIT.lock().unwrap() = true; return; @@ -534,7 +534,7 @@ pub mod client { bail!("already running"); } if SHMEM.lock().unwrap().is_none() { - let displays = scrap::Display::all()?; + let displays = crate::display_service::get_displays(false)?; if displays.is_empty() { bail!("no display available!"); } @@ -655,7 +655,7 @@ pub mod client { shmem.write(ADDR_CAPTURE_WOULDBLOCK, &utils::i32_to_vec(TRUE)); } let (mut width, mut height) = (0, 0); - if let Ok(displays) = display_service::try_get_displays() { + if let Ok(displays) = display_service::try_get_displays(true) { if let Some(display) = displays.get(current_display) { width = display.width(); height = display.height(); diff --git a/src/server/video_service.rs b/src/server/video_service.rs index 22fe7a89f..a8fbcf05f 100644 --- a/src/server/video_service.rs +++ b/src/server/video_service.rs @@ -249,7 +249,7 @@ pub fn test_create_capturer( ) -> String { let test_begin = Instant::now(); loop { - let err = match Display::all() { + let err = match super::display_service::get_displays(true) { Ok(mut displays) => { if displays.len() <= display_idx { anyhow!( @@ -322,7 +322,7 @@ fn get_capturer(current: usize, portable_service_running: bool) -> ResultType ResultType<()> { if *CAP_DISPLAY_INFO.read().unwrap() == 0 { let mut lock = CAP_DISPLAY_INFO.write().unwrap(); if *lock == 0 { - let mut all = Display::all()?; + let mut all = super::display_service::get_displays(true)?; let num = all.len(); let primary = super::display_service::get_primary_2(&all); let current = primary;