Files
galaxy/crates/galaxyui/src/windowing/winit/window/windows_wm.rs
T

123 lines
4.8 KiB
Rust

use std::sync::Arc;
use anyhow::Result;
use itertools::Itertools as _;
use pathfinder_geometry::rect::RectF;
use windows::Win32::Graphics::Gdi::{MonitorFromWindow, MONITOR_DEFAULTTONEAREST};
use windows::Win32::UI::WindowsAndMessaging::GetForegroundWindow;
use winit::monitor::MonitorHandle;
use winit::platform::windows::MonitorHandleExtWindows;
use winit::window::Window as WinitWindow;
use super::get_monitor_logical_bounds;
use crate::platform::WindowManager as _;
use crate::windowing::winit::window::WindowManager;
use crate::{DisplayId, DisplayIdx};
impl WindowManager {
/// Returns the active Warp window. This will return an error if a different app's window is
/// active.
fn get_active_window_handle(&self) -> Result<Arc<WinitWindow>> {
let window_id = &self
.active_window_id()
.ok_or(anyhow::anyhow!("No active window ID"))?;
let ui_window = self
.windows
.get(window_id)
.ok_or(anyhow::anyhow!("Window not found"))?;
let winit_window_borrow = ui_window.inner.try_borrow()?;
let winit_window_ref = winit_window_borrow
.as_ref()
.ok_or(anyhow::anyhow!("Unable to read Window information"))?;
Ok(winit_window_ref.window.clone())
}
fn get_any_window_handle(&self) -> Result<Arc<WinitWindow>> {
self.windows
.values()
.find_map(|window| {
window
.inner
.try_borrow()
.ok()
.and_then(|borrow| borrow.as_ref().map(|inner| inner.window.clone()))
})
.ok_or_else(|| anyhow::anyhow!("No window handles available"))
}
/// Returns the monitor which contains the focused window ("key window" in MacOS parlance). It's
/// the window that receives and handles the keypress events.
fn get_foreground_monitor(&self) -> Result<MonitorHandle> {
let any_window = self.get_any_window_handle()?;
// Even if no window has foreground focus, MonitorFromWindow with
// MONITOR_DEFAULTTONEAREST will return the nearest/primary monitor.
let fg_hwnd = unsafe { GetForegroundWindow() };
let target_hmonitor = unsafe { MonitorFromWindow(fg_hwnd, MONITOR_DEFAULTTONEAREST) };
any_window
.available_monitors()
.find(|monitor| monitor.hmonitor() == target_hmonitor.0 as isize)
.ok_or_else(|| anyhow::anyhow!("Could not match foreground window's monitor"))
}
fn get_active_monitor(&self) -> Result<MonitorHandle> {
self.get_active_window_handle()
.and_then(|w| {
w.current_monitor()
.ok_or_else(|| anyhow::anyhow!("Unable to get current monitor"))
})
.or_else(|_| self.get_foreground_monitor())
}
pub(super) fn get_monitor_bounds_for_display_idx(&self, idx: DisplayIdx) -> Result<RectF> {
let primary_monitor = self.get_primary_monitor_handle()?;
let monitor = match idx {
DisplayIdx::Primary => primary_monitor,
DisplayIdx::External(numerical_index) => {
let monitors = self.get_available_monitors()?;
monitors
.iter()
.filter(|monitor| {
// Filter out the primary monitor.
monitor.hmonitor() != primary_monitor.hmonitor()
})
.nth(numerical_index)
.ok_or(anyhow::anyhow!(
"Could not find monitor handle for {numerical_index:?}"
))?
.to_owned()
}
};
Ok(get_monitor_logical_bounds(&monitor))
}
fn get_primary_monitor_handle(&self) -> Result<MonitorHandle> {
let winit_window_ref = self.get_any_window_handle()?;
winit_window_ref
.primary_monitor()
.ok_or(anyhow::anyhow!("No primary monitor found"))
}
pub(super) fn get_current_monitor_id(&self) -> Result<DisplayId> {
let active_monitor = self.get_active_monitor()?;
let active_monitor_id = active_monitor.hmonitor();
Ok(DisplayId::from(active_monitor_id as usize))
}
fn get_available_monitors(&self) -> Result<Vec<MonitorHandle>> {
let winit_window_ref = self.get_any_window_handle()?;
Ok(winit_window_ref.available_monitors().collect_vec())
}
pub(super) fn get_available_monitor_count(&self) -> Result<usize> {
let winit_window_ref = self.get_any_window_handle()?;
Ok(winit_window_ref.available_monitors().count())
}
pub(super) fn get_active_monitor_logical_bounds(&self) -> Result<RectF> {
let active_monitor = self.get_active_monitor()?;
Ok(get_monitor_logical_bounds(&active_monitor))
}
}