2018-06-14 19:42:18 -04:00
|
|
|
use winapi::shared::minwindef::{BOOL, DWORD, LPARAM, TRUE};
|
|
|
|
|
use winapi::shared::windef::{HDC, HMONITOR, HWND, LPRECT, POINT};
|
2018-07-01 11:01:46 -04:00
|
|
|
use winapi::um::winnt::LONG;
|
2017-12-24 15:46:47 +02:00
|
|
|
use winapi::um::winuser;
|
2014-07-31 10:52:05 +02:00
|
|
|
|
2017-10-25 18:12:39 +03:00
|
|
|
use std::{mem, ptr};
|
2018-06-14 19:42:18 -04:00
|
|
|
use std::collections::VecDeque;
|
2015-01-01 23:09:16 -08:00
|
|
|
|
2019-02-05 10:30:33 -05:00
|
|
|
use super::{EventLoop, util};
|
2018-06-16 10:14:12 -04:00
|
|
|
use dpi::{PhysicalPosition, PhysicalSize};
|
2019-02-05 10:30:33 -05:00
|
|
|
use platform_impl::platform::dpi::{dpi_to_scale_factor, get_monitor_dpi};
|
|
|
|
|
use platform_impl::platform::window::Window;
|
2017-09-01 11:04:57 +02:00
|
|
|
|
2019-02-05 10:30:33 -05:00
|
|
|
/// Win32 implementation of the main `MonitorHandle` object.
|
2018-05-14 08:14:57 -04:00
|
|
|
#[derive(Debug, Clone)]
|
2019-02-05 10:30:33 -05:00
|
|
|
pub struct MonitorHandle {
|
2017-10-25 18:12:39 +03:00
|
|
|
/// Monitor handle.
|
|
|
|
|
hmonitor: HMonitor,
|
2014-08-01 23:02:26 +02:00
|
|
|
/// The system name of the monitor.
|
2015-03-24 13:29:17 -07:00
|
|
|
monitor_name: String,
|
2015-04-12 09:32:25 +02:00
|
|
|
/// True if this is the primary monitor.
|
|
|
|
|
primary: bool,
|
2014-08-01 23:02:26 +02:00
|
|
|
/// The position of the monitor in pixels on the desktop.
|
|
|
|
|
///
|
2017-10-19 20:08:05 +03:00
|
|
|
/// A window that is positioned at these coordinates will overlap the monitor.
|
|
|
|
|
position: (i32, i32),
|
2014-08-02 11:17:49 +02:00
|
|
|
/// The current resolution in pixels on the monitor.
|
2015-01-13 15:21:36 +03:00
|
|
|
dimensions: (u32, u32),
|
2018-06-14 19:42:18 -04:00
|
|
|
/// DPI scale factor.
|
|
|
|
|
hidpi_factor: f64,
|
2015-03-24 13:29:17 -07:00
|
|
|
}
|
2014-07-31 10:52:05 +02:00
|
|
|
|
2017-10-25 18:12:39 +03:00
|
|
|
// Send is not implemented for HMONITOR, we have to wrap it and implement it manually.
|
|
|
|
|
// For more info see:
|
|
|
|
|
// https://github.com/retep998/winapi-rs/issues/360
|
|
|
|
|
// https://github.com/retep998/winapi-rs/issues/396
|
2018-05-14 08:14:57 -04:00
|
|
|
#[derive(Debug, Clone)]
|
2017-12-24 15:46:47 +02:00
|
|
|
struct HMonitor(HMONITOR);
|
2014-08-01 23:02:26 +02:00
|
|
|
|
2017-10-25 18:12:39 +03:00
|
|
|
unsafe impl Send for HMonitor {}
|
2014-07-31 10:52:05 +02:00
|
|
|
|
2018-06-14 19:42:18 -04:00
|
|
|
unsafe extern "system" fn monitor_enum_proc(
|
|
|
|
|
hmonitor: HMONITOR,
|
|
|
|
|
_hdc: HDC,
|
|
|
|
|
_place: LPRECT,
|
|
|
|
|
data: LPARAM,
|
|
|
|
|
) -> BOOL {
|
2019-02-05 10:30:33 -05:00
|
|
|
let monitors = data as *mut VecDeque<MonitorHandle>;
|
|
|
|
|
(*monitors).push_back(MonitorHandle::from_hmonitor(hmonitor));
|
2018-06-14 19:42:18 -04:00
|
|
|
TRUE // continue enumeration
|
2017-10-25 18:12:39 +03:00
|
|
|
}
|
|
|
|
|
|
2019-02-05 10:30:33 -05:00
|
|
|
pub fn get_available_monitors() -> VecDeque<MonitorHandle> {
|
|
|
|
|
let mut monitors: VecDeque<MonitorHandle> = VecDeque::new();
|
2018-06-16 10:14:12 -04:00
|
|
|
unsafe {
|
|
|
|
|
winuser::EnumDisplayMonitors(
|
|
|
|
|
ptr::null_mut(),
|
|
|
|
|
ptr::null_mut(),
|
|
|
|
|
Some(monitor_enum_proc),
|
|
|
|
|
&mut monitors as *mut _ as LPARAM,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
monitors
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-05 10:30:33 -05:00
|
|
|
pub fn get_primary_monitor() -> MonitorHandle {
|
2018-06-16 10:14:12 -04:00
|
|
|
const ORIGIN: POINT = POINT { x: 0, y: 0 };
|
|
|
|
|
let hmonitor = unsafe {
|
|
|
|
|
winuser::MonitorFromPoint(ORIGIN, winuser::MONITOR_DEFAULTTOPRIMARY)
|
|
|
|
|
};
|
2019-02-05 10:30:33 -05:00
|
|
|
MonitorHandle::from_hmonitor(hmonitor)
|
2018-06-16 10:14:12 -04:00
|
|
|
}
|
|
|
|
|
|
2019-02-05 10:30:33 -05:00
|
|
|
pub fn get_current_monitor(hwnd: HWND) -> MonitorHandle {
|
|
|
|
|
let hmonitor = unsafe {
|
|
|
|
|
winuser::MonitorFromWindow(hwnd, winuser::MONITOR_DEFAULTTONEAREST)
|
|
|
|
|
};
|
|
|
|
|
MonitorHandle::from_hmonitor(hmonitor)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T> EventLoop<T> {
|
2018-06-14 19:42:18 -04:00
|
|
|
// TODO: Investigate opportunities for caching
|
2019-02-05 10:30:33 -05:00
|
|
|
pub fn get_available_monitors(&self) -> VecDeque<MonitorHandle> {
|
2018-06-16 10:14:12 -04:00
|
|
|
get_available_monitors()
|
2014-07-31 10:52:05 +02:00
|
|
|
}
|
|
|
|
|
|
2019-02-05 10:30:33 -05:00
|
|
|
pub fn get_primary_monitor(&self) -> MonitorHandle {
|
2018-06-16 10:14:12 -04:00
|
|
|
get_primary_monitor()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Window {
|
2019-02-05 10:30:33 -05:00
|
|
|
pub fn get_available_monitors(&self) -> VecDeque<MonitorHandle> {
|
2018-06-16 10:14:12 -04:00
|
|
|
get_available_monitors()
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-05 10:30:33 -05:00
|
|
|
pub fn get_primary_monitor(&self) -> MonitorHandle {
|
2018-06-16 10:14:12 -04:00
|
|
|
get_primary_monitor()
|
2018-06-14 19:42:18 -04:00
|
|
|
}
|
|
|
|
|
}
|
2014-07-31 10:52:05 +02:00
|
|
|
|
2019-02-04 11:52:00 -05:00
|
|
|
pub(crate) fn get_monitor_info(hmonitor: HMONITOR) -> Result<winuser::MONITORINFOEXW, util::WinError> {
|
2018-06-14 19:42:18 -04:00
|
|
|
let mut monitor_info: winuser::MONITORINFOEXW = unsafe { mem::uninitialized() };
|
|
|
|
|
monitor_info.cbSize = mem::size_of::<winuser::MONITORINFOEXW>() as DWORD;
|
|
|
|
|
let status = unsafe {
|
|
|
|
|
winuser::GetMonitorInfoW(
|
|
|
|
|
hmonitor,
|
|
|
|
|
&mut monitor_info as *mut winuser::MONITORINFOEXW as *mut winuser::MONITORINFO,
|
|
|
|
|
)
|
|
|
|
|
};
|
|
|
|
|
if status == 0 {
|
|
|
|
|
Err(util::WinError::from_last_error())
|
|
|
|
|
} else {
|
|
|
|
|
Ok(monitor_info)
|
2017-09-01 11:04:57 +02:00
|
|
|
}
|
2014-07-31 10:52:05 +02:00
|
|
|
}
|
|
|
|
|
|
2019-02-05 10:30:33 -05:00
|
|
|
impl MonitorHandle {
|
2018-06-14 19:42:18 -04:00
|
|
|
pub(crate) fn from_hmonitor(hmonitor: HMONITOR) -> Self {
|
|
|
|
|
let monitor_info = get_monitor_info(hmonitor).expect("`GetMonitorInfoW` failed");
|
|
|
|
|
let place = monitor_info.rcMonitor;
|
|
|
|
|
let dimensions = (
|
|
|
|
|
(place.right - place.left) as u32,
|
|
|
|
|
(place.bottom - place.top) as u32,
|
|
|
|
|
);
|
2019-02-05 10:30:33 -05:00
|
|
|
MonitorHandle {
|
2018-06-14 19:42:18 -04:00
|
|
|
hmonitor: HMonitor(hmonitor),
|
|
|
|
|
monitor_name: util::wchar_ptr_to_string(monitor_info.szDevice.as_ptr()),
|
|
|
|
|
primary: util::has_flag(monitor_info.dwFlags, winuser::MONITORINFOF_PRIMARY),
|
|
|
|
|
position: (place.left as i32, place.top as i32),
|
|
|
|
|
dimensions,
|
|
|
|
|
hidpi_factor: dpi_to_scale_factor(get_monitor_dpi(hmonitor).unwrap_or(96)),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-01 11:01:46 -04:00
|
|
|
pub(crate) fn contains_point(&self, point: &POINT) -> bool {
|
|
|
|
|
let left = self.position.0 as LONG;
|
|
|
|
|
let right = left + self.dimensions.0 as LONG;
|
|
|
|
|
let top = self.position.1 as LONG;
|
|
|
|
|
let bottom = top + self.dimensions.1 as LONG;
|
|
|
|
|
point.x >= left && point.x <= right && point.y >= top && point.y <= bottom
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-21 14:42:05 +02:00
|
|
|
#[inline]
|
2014-07-31 10:52:05 +02:00
|
|
|
pub fn get_name(&self) -> Option<String> {
|
2017-10-25 18:12:39 +03:00
|
|
|
Some(self.monitor_name.clone())
|
2014-07-31 10:52:05 +02:00
|
|
|
}
|
|
|
|
|
|
2015-09-21 14:42:05 +02:00
|
|
|
#[inline]
|
2017-08-30 08:49:18 +02:00
|
|
|
pub fn get_native_identifier(&self) -> String {
|
|
|
|
|
self.monitor_name.clone()
|
2015-03-16 13:52:58 -07:00
|
|
|
}
|
|
|
|
|
|
2017-10-25 18:12:39 +03:00
|
|
|
#[inline]
|
2017-12-24 15:46:47 +02:00
|
|
|
pub fn get_hmonitor(&self) -> HMONITOR {
|
2017-10-25 18:12:39 +03:00
|
|
|
self.hmonitor.0
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-21 14:42:05 +02:00
|
|
|
#[inline]
|
2018-06-14 19:42:18 -04:00
|
|
|
pub fn get_dimensions(&self) -> PhysicalSize {
|
|
|
|
|
self.dimensions.into()
|
2014-08-02 11:17:49 +02:00
|
|
|
}
|
|
|
|
|
|
2015-09-21 14:42:05 +02:00
|
|
|
#[inline]
|
2018-06-14 19:42:18 -04:00
|
|
|
pub fn get_position(&self) -> PhysicalPosition {
|
|
|
|
|
self.position.into()
|
2014-07-31 10:52:05 +02:00
|
|
|
}
|
2017-10-17 14:56:38 +03:00
|
|
|
|
|
|
|
|
#[inline]
|
2018-06-14 19:42:18 -04:00
|
|
|
pub fn get_hidpi_factor(&self) -> f64 {
|
2017-10-25 18:12:39 +03:00
|
|
|
self.hidpi_factor
|
2017-10-17 14:56:38 +03:00
|
|
|
}
|
2014-07-31 10:52:05 +02:00
|
|
|
}
|