1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-23 13:21:38 +03:00

lua: implement wezterm.window.screens() on Windows

This commit is contained in:
Wez Furlong 2022-07-06 08:58:07 -07:00
parent 9301d1900d
commit cdeabd6a21

View File

@ -1,12 +1,17 @@
//! The connection to the GUI subsystem
use super::{HWindow, WindowInner};
use crate::connection::ConnectionOps;
use crate::screen::{ScreenInfo, Screens};
use crate::spawn::*;
use crate::Appearance;
use crate::{Appearance, ScreenRect};
use std::cell::RefCell;
use std::collections::HashMap;
use std::ffi::OsString;
use std::os::windows::ffi::OsStringExt;
use std::ptr::null_mut;
use std::rc::Rc;
use winapi::shared::minwindef::*;
use winapi::shared::windef::*;
use winapi::um::winbase::INFINITE;
use winapi::um::winnt::HANDLE;
use winapi::um::winuser::*;
@ -77,6 +82,84 @@ impl ConnectionOps for Connection {
MessageBeep(MB_OK);
}
}
fn screens(&self) -> anyhow::Result<Screens> {
// Iterate the monitors.
// The device names are things like "\\.\DISPLAY1" which isn't super
// user friendly. There may be an alternative API to get a better name,
// but for now this is good enough.
struct Info {
primary: Option<ScreenInfo>,
by_name: HashMap<String, ScreenInfo>,
virtual_rect: ScreenRect,
}
unsafe extern "system" fn callback(
mon: HMONITOR,
_hdc: HDC,
_rect: *mut RECT,
data: LPARAM,
) -> i32 {
let info: &mut Info = &mut *(data as *mut Info);
let mut mi: MONITORINFOEXW = std::mem::zeroed();
mi.cbSize = std::mem::size_of::<MONITORINFOEXW>() as u32;
GetMonitorInfoW(mon, &mut mi as *mut MONITORINFOEXW as *mut MONITORINFO);
// "\\.\DISPLAY1" -> "DISPLAY1"
let len = mi.szDevice.iter().position(|&c| c == 0).unwrap_or(0);
let monitor_name = OsString::from_wide(&mi.szDevice[0..len])
.to_string_lossy()
.to_string();
let monitor_name = if let Some(name) = monitor_name.strip_prefix("\\\\.\\") {
name.to_string()
} else {
monitor_name
};
let screen_info = ScreenInfo {
name: monitor_name.clone(),
rect: euclid::rect(
mi.rcMonitor.left as isize,
mi.rcMonitor.top as isize,
mi.rcMonitor.right as isize - mi.rcMonitor.left as isize,
mi.rcMonitor.bottom as isize - mi.rcMonitor.top as isize,
),
};
info.virtual_rect = info.virtual_rect.union(&screen_info.rect);
if mi.dwFlags & MONITORINFOF_PRIMARY == MONITORINFOF_PRIMARY {
info.primary.replace(screen_info.clone());
}
info.by_name.insert(monitor_name, screen_info);
winapi::shared::ntdef::TRUE.into()
}
let mut info = Info {
primary: None,
by_name: HashMap::new(),
virtual_rect: euclid::rect(0, 0, 0, 0),
};
unsafe {
EnumDisplayMonitors(
std::ptr::null_mut(),
std::ptr::null(),
Some(callback),
&mut info as *mut _ as LPARAM,
);
}
let main = info
.primary
.ok_or_else(|| anyhow::anyhow!("There is no primary monitor configured!?"))?;
Ok(Screens {
main,
by_name: info.by_name,
virtual_rect: info.virtual_rect,
})
}
}
impl Connection {