#![allow(unsafe_code)]
use dais_core::monitor::{MonitorInfo, MonitorManager};
use std::mem;
use windows::Win32::Foundation::{LPARAM, RECT};
use windows::Win32::Graphics::Gdi::{
DISPLAY_DEVICEW, EnumDisplayDevicesW, EnumDisplayMonitors, GetMonitorInfoW, HDC, HMONITOR,
MONITORINFOEXW,
};
use windows::Win32::UI::HiDpi::{GetDpiForMonitor, MDT_EFFECTIVE_DPI};
use windows::core::{BOOL, PCWSTR};
pub struct WindowsMonitorManager;
impl WindowsMonitorManager {
pub fn new() -> Self {
Self
}
}
impl Default for WindowsMonitorManager {
fn default() -> Self {
Self::new()
}
}
impl MonitorManager for WindowsMonitorManager {
#[allow(unsafe_code)]
fn available_monitors(&self) -> Vec<MonitorInfo> {
let mut monitors = Vec::new();
let monitors_ptr: *mut Vec<MonitorInfo> = &raw mut monitors;
unsafe {
let _ = EnumDisplayMonitors(
None,
None,
Some(monitor_enum_callback),
LPARAM(monitors_ptr as isize),
);
}
monitors
}
}
#[allow(clippy::cast_sign_loss)]
unsafe extern "system" fn monitor_enum_callback(
hmonitor: HMONITOR,
_hdc: HDC,
_lprect: *mut RECT,
lparam: LPARAM,
) -> BOOL {
let monitors = unsafe { &mut *(lparam.0 as *mut Vec<MonitorInfo>) };
let mut info: MONITORINFOEXW = unsafe { mem::zeroed() };
#[allow(clippy::cast_possible_truncation)]
let cb_size = mem::size_of::<MONITORINFOEXW>() as u32;
info.monitorInfo.cbSize = cb_size;
if !unsafe { GetMonitorInfoW(hmonitor, (&raw mut info).cast()) }.as_bool() {
return BOOL(1); }
let rc = info.monitorInfo.rcMonitor;
let rc_work = info.monitorInfo.rcWork;
let width = (rc.right - rc.left) as u32;
let height = (rc.bottom - rc.top) as u32;
let work_width = (rc_work.right - rc_work.left) as u32;
let work_height = (rc_work.bottom - rc_work.top) as u32;
let is_primary = (info.monitorInfo.dwFlags & 1) != 0;
let mut dpi_x: u32 = 96;
let mut dpi_y: u32 = 96;
let _ =
unsafe { GetDpiForMonitor(hmonitor, MDT_EFFECTIVE_DPI, &raw mut dpi_x, &raw mut dpi_y) };
let scale_factor = f64::from(dpi_x) / 96.0;
let device_name = wstr_to_string(&info.szDevice);
let friendly_name = unsafe { get_friendly_name(&info.szDevice) };
let name = friendly_name.unwrap_or_else(|| device_name.clone());
let id = format!("{device_name}@{}x{}", rc.left, rc.top);
monitors.push(MonitorInfo {
id,
name,
position: (rc.left, rc.top),
size: (width, height),
work_area: (rc_work.left, rc_work.top, work_width, work_height),
scale_factor,
is_primary,
});
BOOL(1) }
unsafe fn get_friendly_name(device_name: &[u16; 32]) -> Option<String> {
let mut display_device: DISPLAY_DEVICEW = unsafe { mem::zeroed() };
#[allow(clippy::cast_possible_truncation)]
let cb = mem::size_of::<DISPLAY_DEVICEW>() as u32;
display_device.cb = cb;
let device_name_pcwstr = PCWSTR::from_raw(device_name.as_ptr());
if !unsafe { EnumDisplayDevicesW(device_name_pcwstr, 0, &raw mut display_device, 1) }.as_bool()
{
return None;
}
let name = wstr_to_string(&display_device.DeviceString);
if name.is_empty() { None } else { Some(name) }
}
fn wstr_to_string(buf: &[u16]) -> String {
let len = buf.iter().position(|&c| c == 0).unwrap_or(buf.len());
String::from_utf16_lossy(&buf[..len])
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn enumerate_at_least_one_monitor() {
let mgr = WindowsMonitorManager::new();
let monitors = mgr.available_monitors();
assert!(!monitors.is_empty(), "should detect at least one monitor");
}
#[test]
fn has_one_primary() {
let mgr = WindowsMonitorManager::new();
let monitors = mgr.available_monitors();
let primary_count = monitors.iter().filter(|m| m.is_primary).count();
assert_eq!(primary_count, 1, "exactly one monitor should be primary");
}
#[test]
fn monitor_has_nonzero_size() {
let mgr = WindowsMonitorManager::new();
for m in mgr.available_monitors() {
assert!(m.size.0 > 0, "monitor width should be > 0: {}", m.name);
assert!(m.size.1 > 0, "monitor height should be > 0: {}", m.name);
}
}
#[test]
fn scale_factor_is_reasonable() {
let mgr = WindowsMonitorManager::new();
for m in mgr.available_monitors() {
assert!(
(0.5..=4.0).contains(&m.scale_factor),
"scale factor {} out of expected range for {}",
m.scale_factor,
m.name
);
}
}
#[test]
fn primary_monitor_helper_works() {
let mgr = WindowsMonitorManager::new();
let primary = mgr.primary_monitor();
assert!(primary.is_some(), "primary_monitor() should return Some");
assert!(primary.unwrap().is_primary);
}
#[test]
fn logical_size_computation() {
let info = MonitorInfo {
id: "test".into(),
name: "Test".into(),
position: (0, 0),
size: (3840, 2160),
work_area: (0, 0, 3840, 2080),
scale_factor: 2.0,
is_primary: true,
};
let (lw, lh) = info.logical_size();
assert!((lw - 1920.0).abs() < f64::EPSILON);
assert!((lh - 1080.0).abs() < f64::EPSILON);
}
}