mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-25 06:41:31 +11:00
Merge pull request #324 from binsoftware/win32-monitor
Win32 monitor handling
This commit is contained in:
commit
8c78cabcf2
|
@ -164,6 +164,12 @@ unsafe fn init(title: Vec<u16>, builder: BuilderAttribs<'static>,
|
||||||
(None, None)
|
(None, None)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let (x, y) = if builder.monitor.is_some() {
|
||||||
|
(Some(rect.left), Some(rect.top))
|
||||||
|
} else {
|
||||||
|
(None, None)
|
||||||
|
};
|
||||||
|
|
||||||
let style = if !builder.visible || builder.headless {
|
let style = if !builder.visible || builder.headless {
|
||||||
style
|
style
|
||||||
} else {
|
} else {
|
||||||
|
@ -173,8 +179,7 @@ unsafe fn init(title: Vec<u16>, builder: BuilderAttribs<'static>,
|
||||||
let handle = user32::CreateWindowExW(ex_style, class_name.as_ptr(),
|
let handle = user32::CreateWindowExW(ex_style, class_name.as_ptr(),
|
||||||
title.as_ptr() as winapi::LPCWSTR,
|
title.as_ptr() as winapi::LPCWSTR,
|
||||||
style | winapi::WS_CLIPSIBLINGS | winapi::WS_CLIPCHILDREN,
|
style | winapi::WS_CLIPSIBLINGS | winapi::WS_CLIPCHILDREN,
|
||||||
if builder.monitor.is_some() { 0 } else { winapi::CW_USEDEFAULT },
|
x.unwrap_or(winapi::CW_USEDEFAULT), y.unwrap_or(winapi::CW_USEDEFAULT),
|
||||||
if builder.monitor.is_some() { 0 } else { winapi::CW_USEDEFAULT },
|
|
||||||
width.unwrap_or(winapi::CW_USEDEFAULT), height.unwrap_or(winapi::CW_USEDEFAULT),
|
width.unwrap_or(winapi::CW_USEDEFAULT), height.unwrap_or(winapi::CW_USEDEFAULT),
|
||||||
ptr::null_mut(), ptr::null_mut(), kernel32::GetModuleHandleW(ptr::null()),
|
ptr::null_mut(), ptr::null_mut(), kernel32::GetModuleHandleW(ptr::null()),
|
||||||
ptr::null_mut());
|
ptr::null_mut());
|
||||||
|
@ -296,7 +301,7 @@ unsafe fn switch_to_fullscreen(rect: &mut winapi::RECT, monitor: &MonitorID)
|
||||||
screen_settings.dmBitsPerPel = 32; // TODO: ?
|
screen_settings.dmBitsPerPel = 32; // TODO: ?
|
||||||
screen_settings.dmFields = winapi::DM_BITSPERPEL | winapi::DM_PELSWIDTH | winapi::DM_PELSHEIGHT;
|
screen_settings.dmFields = winapi::DM_BITSPERPEL | winapi::DM_PELSWIDTH | winapi::DM_PELSHEIGHT;
|
||||||
|
|
||||||
let result = user32::ChangeDisplaySettingsExW(monitor.get_system_name().as_ptr(),
|
let result = user32::ChangeDisplaySettingsExW(monitor.get_adapter_name().as_ptr(),
|
||||||
&mut screen_settings, ptr::null_mut(),
|
&mut screen_settings, ptr::null_mut(),
|
||||||
winapi::CDS_FULLSCREEN, ptr::null_mut());
|
winapi::CDS_FULLSCREEN, ptr::null_mut());
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,11 @@ use native_monitor::NativeMonitorId;
|
||||||
|
|
||||||
/// Win32 implementation of the main `MonitorID` object.
|
/// Win32 implementation of the main `MonitorID` object.
|
||||||
pub struct MonitorID {
|
pub struct MonitorID {
|
||||||
|
/// The system name of the adapter.
|
||||||
|
adapter_name: [winapi::WCHAR; 32],
|
||||||
|
|
||||||
/// The system name of the monitor.
|
/// The system name of the monitor.
|
||||||
name: [winapi::WCHAR; 32],
|
monitor_name: String,
|
||||||
|
|
||||||
/// Name to give to the user.
|
/// Name to give to the user.
|
||||||
readable_name: String,
|
readable_name: String,
|
||||||
|
@ -26,27 +29,43 @@ pub struct MonitorID {
|
||||||
dimensions: (u32, u32),
|
dimensions: (u32, u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Win32 implementation of the main `get_available_monitors` function.
|
struct DeviceEnumerator {
|
||||||
pub fn get_available_monitors() -> VecDeque<MonitorID> {
|
parent_device: *const winapi::WCHAR,
|
||||||
use std::{iter, mem, ptr};
|
current_index: u32,
|
||||||
|
}
|
||||||
|
|
||||||
// return value
|
impl DeviceEnumerator {
|
||||||
let mut result = VecDeque::new();
|
fn adapters() -> DeviceEnumerator {
|
||||||
|
use std::ptr;
|
||||||
|
DeviceEnumerator {
|
||||||
|
parent_device: ptr::null(),
|
||||||
|
current_index: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// enumerating the devices is done by querying device 0, then device 1, then device 2, etc.
|
fn monitors(adapter_name: *const winapi::WCHAR) -> DeviceEnumerator {
|
||||||
// until the query function returns null
|
DeviceEnumerator {
|
||||||
for id in iter::count(0u32, 1) {
|
parent_device: adapter_name,
|
||||||
// getting the DISPLAY_DEVICEW object of the current device
|
current_index: 0
|
||||||
let output = {
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for DeviceEnumerator {
|
||||||
|
type Item = winapi::DISPLAY_DEVICEW;
|
||||||
|
fn next(&mut self) -> Option<winapi::DISPLAY_DEVICEW> {
|
||||||
|
use std::mem;
|
||||||
|
loop {
|
||||||
let mut output: winapi::DISPLAY_DEVICEW = unsafe { mem::zeroed() };
|
let mut output: winapi::DISPLAY_DEVICEW = unsafe { mem::zeroed() };
|
||||||
output.cb = mem::size_of::<winapi::DISPLAY_DEVICEW>() as winapi::DWORD;
|
output.cb = mem::size_of::<winapi::DISPLAY_DEVICEW>() as winapi::DWORD;
|
||||||
|
|
||||||
if unsafe { user32::EnumDisplayDevicesW(ptr::null(),
|
if unsafe { user32::EnumDisplayDevicesW(self.parent_device,
|
||||||
id as winapi::DWORD, &mut output, 0) } == 0
|
self.current_index as winapi::DWORD, &mut output, 0) } == 0
|
||||||
{
|
{
|
||||||
// the device doesn't exist, which means we have finished enumerating
|
// the device doesn't exist, which means we have finished enumerating
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
self.current_index += 1;
|
||||||
|
|
||||||
if (output.StateFlags & winapi::DISPLAY_DEVICE_ACTIVE) == 0 ||
|
if (output.StateFlags & winapi::DISPLAY_DEVICE_ACTIVE) == 0 ||
|
||||||
(output.StateFlags & winapi::DISPLAY_DEVICE_MIRRORING_DRIVER) != 0
|
(output.StateFlags & winapi::DISPLAY_DEVICE_MIRRORING_DRIVER) != 0
|
||||||
|
@ -56,19 +75,34 @@ pub fn get_available_monitors() -> VecDeque<MonitorID> {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
output
|
return Some(output);
|
||||||
};
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// computing the human-friendly name
|
fn wchar_as_string(wchar: &[winapi::WCHAR]) -> String {
|
||||||
let readable_name = String::from_utf16_lossy(output.DeviceString.as_slice());
|
String::from_utf16_lossy(wchar)
|
||||||
let readable_name = readable_name.as_slice().trim_right_matches(0 as char).to_string();
|
.as_slice()
|
||||||
|
.trim_right_matches(0 as char)
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Win32 implementation of the main `get_available_monitors` function.
|
||||||
|
pub fn get_available_monitors() -> VecDeque<MonitorID> {
|
||||||
|
use std::{iter, mem, ptr};
|
||||||
|
|
||||||
|
// return value
|
||||||
|
let mut result = VecDeque::new();
|
||||||
|
|
||||||
|
for adapter in DeviceEnumerator::adapters() {
|
||||||
// getting the position
|
// getting the position
|
||||||
let (position, dimensions) = unsafe {
|
let (position, dimensions) = unsafe {
|
||||||
let mut dev: winapi::DEVMODEW = mem::zeroed();
|
let mut dev: winapi::DEVMODEW = mem::zeroed();
|
||||||
dev.dmSize = mem::size_of::<winapi::DEVMODEW>() as winapi::WORD;
|
dev.dmSize = mem::size_of::<winapi::DEVMODEW>() as winapi::WORD;
|
||||||
|
|
||||||
if user32::EnumDisplaySettingsExW(output.DeviceName.as_ptr(), winapi::ENUM_CURRENT_SETTINGS,
|
if user32::EnumDisplaySettingsExW(adapter.DeviceName.as_ptr(),
|
||||||
|
winapi::ENUM_CURRENT_SETTINGS,
|
||||||
&mut dev, 0) == 0
|
&mut dev, 0) == 0
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
@ -82,16 +116,18 @@ pub fn get_available_monitors() -> VecDeque<MonitorID> {
|
||||||
(position, dimensions)
|
(position, dimensions)
|
||||||
};
|
};
|
||||||
|
|
||||||
// adding to the resulting list
|
for monitor in DeviceEnumerator::monitors(adapter.DeviceName.as_ptr()) {
|
||||||
result.push_back(MonitorID {
|
// adding to the resulting list
|
||||||
name: output.DeviceName,
|
result.push_back(MonitorID {
|
||||||
readable_name: readable_name,
|
adapter_name: adapter.DeviceName,
|
||||||
flags: output.StateFlags,
|
monitor_name: wchar_as_string(monitor.DeviceName.as_slice()),
|
||||||
position: position,
|
readable_name: wchar_as_string(monitor.DeviceString.as_slice()),
|
||||||
dimensions: dimensions,
|
flags: monitor.StateFlags,
|
||||||
});
|
position: position,
|
||||||
|
dimensions: dimensions,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +153,7 @@ impl MonitorID {
|
||||||
|
|
||||||
/// See the docs of the crate root file.
|
/// See the docs of the crate root file.
|
||||||
pub fn get_native_identifier(&self) -> NativeMonitorId {
|
pub fn get_native_identifier(&self) -> NativeMonitorId {
|
||||||
NativeMonitorId::Name(self.readable_name.clone())
|
NativeMonitorId::Name(self.monitor_name.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See the docs if the crate root file.
|
/// See the docs if the crate root file.
|
||||||
|
@ -126,10 +162,10 @@ impl MonitorID {
|
||||||
self.dimensions
|
self.dimensions
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is a Win32-only function for `MonitorID` that returns the system name of the device.
|
/// This is a Win32-only function for `MonitorID` that returns the system name of the adapter
|
||||||
pub fn get_system_name(&self) -> &[winapi::WCHAR] {
|
/// device.
|
||||||
// TODO: retreive the position every time this is called
|
pub fn get_adapter_name(&self) -> &[winapi::WCHAR] {
|
||||||
self.name.as_slice()
|
self.adapter_name.as_slice()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is a Win32-only function for `MonitorID` that returns the position of the
|
/// This is a Win32-only function for `MonitorID` that returns the position of the
|
||||||
|
|
Loading…
Reference in a new issue