aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortomaka <pierre.krieger1708@gmail.com>2015-03-25 06:17:35 +0100
committertomaka <pierre.krieger1708@gmail.com>2015-03-25 06:17:35 +0100
commit8c78cabcf29f7a04ceffdafb597824759870e574 (patch)
treee6d7b5e256a085a3844dbabb7fe8fc3d7b2790fd
parentd0dad79d4ce49d8a3daf90467fdf9556749f2aeb (diff)
parent1c9c5c018a24ebd5593c15b184d36945793aff5e (diff)
downloadglutin-8c78cabcf29f7a04ceffdafb597824759870e574.tar.gz
glutin-8c78cabcf29f7a04ceffdafb597824759870e574.zip
Merge pull request #324 from binsoftware/win32-monitor
Win32 monitor handling
-rw-r--r--src/win32/init.rs11
-rw-r--r--src/win32/monitor.rs102
2 files changed, 77 insertions, 36 deletions
diff --git a/src/win32/init.rs b/src/win32/init.rs
index b458d95..8d2eb1e 100644
--- a/src/win32/init.rs
+++ b/src/win32/init.rs
@@ -164,6 +164,12 @@ unsafe fn init(title: Vec<u16>, builder: BuilderAttribs<'static>,
(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 {
style
} else {
@@ -173,8 +179,7 @@ unsafe fn init(title: Vec<u16>, builder: BuilderAttribs<'static>,
let handle = user32::CreateWindowExW(ex_style, class_name.as_ptr(),
title.as_ptr() as winapi::LPCWSTR,
style | winapi::WS_CLIPSIBLINGS | winapi::WS_CLIPCHILDREN,
- if builder.monitor.is_some() { 0 } else { winapi::CW_USEDEFAULT },
- if builder.monitor.is_some() { 0 } else { winapi::CW_USEDEFAULT },
+ x.unwrap_or(winapi::CW_USEDEFAULT), y.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());
@@ -296,7 +301,7 @@ unsafe fn switch_to_fullscreen(rect: &mut winapi::RECT, monitor: &MonitorID)
screen_settings.dmBitsPerPel = 32; // TODO: ?
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(),
winapi::CDS_FULLSCREEN, ptr::null_mut());
diff --git a/src/win32/monitor.rs b/src/win32/monitor.rs
index 819aa7f..b5ffe2d 100644
--- a/src/win32/monitor.rs
+++ b/src/win32/monitor.rs
@@ -7,8 +7,11 @@ use native_monitor::NativeMonitorId;
/// Win32 implementation of the main `MonitorID` object.
pub struct MonitorID {
+ /// The system name of the adapter.
+ adapter_name: [winapi::WCHAR; 32],
+
/// The system name of the monitor.
- name: [winapi::WCHAR; 32],
+ monitor_name: String,
/// Name to give to the user.
readable_name: String,
@@ -26,27 +29,43 @@ pub struct MonitorID {
dimensions: (u32, u32),
}
-/// Win32 implementation of the main `get_available_monitors` function.
-pub fn get_available_monitors() -> VecDeque<MonitorID> {
- use std::{iter, mem, ptr};
+struct DeviceEnumerator {
+ parent_device: *const winapi::WCHAR,
+ current_index: u32,
+}
- // return value
- let mut result = VecDeque::new();
+impl DeviceEnumerator {
+ 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.
- // until the query function returns null
- for id in iter::count(0u32, 1) {
- // getting the DISPLAY_DEVICEW object of the current device
- let output = {
+ fn monitors(adapter_name: *const winapi::WCHAR) -> DeviceEnumerator {
+ DeviceEnumerator {
+ parent_device: adapter_name,
+ current_index: 0
+ }
+ }
+}
+
+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() };
output.cb = mem::size_of::<winapi::DISPLAY_DEVICEW>() as winapi::DWORD;
- if unsafe { user32::EnumDisplayDevicesW(ptr::null(),
- id as winapi::DWORD, &mut output, 0) } == 0
+ if unsafe { user32::EnumDisplayDevicesW(self.parent_device,
+ self.current_index as winapi::DWORD, &mut output, 0) } == 0
{
// the device doesn't exist, which means we have finished enumerating
break;
}
+ self.current_index += 1;
if (output.StateFlags & winapi::DISPLAY_DEVICE_ACTIVE) == 0 ||
(output.StateFlags & winapi::DISPLAY_DEVICE_MIRRORING_DRIVER) != 0
@@ -56,19 +75,34 @@ pub fn get_available_monitors() -> VecDeque<MonitorID> {
continue;
}
- output
- };
+ return Some(output);
+ }
+ None
+ }
+}
- // computing the human-friendly name
- let readable_name = String::from_utf16_lossy(output.DeviceString.as_slice());
- let readable_name = readable_name.as_slice().trim_right_matches(0 as char).to_string();
+fn wchar_as_string(wchar: &[winapi::WCHAR]) -> String {
+ String::from_utf16_lossy(wchar)
+ .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
let (position, dimensions) = unsafe {
let mut dev: winapi::DEVMODEW = mem::zeroed();
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
{
continue;
@@ -82,16 +116,18 @@ pub fn get_available_monitors() -> VecDeque<MonitorID> {
(position, dimensions)
};
- // adding to the resulting list
- result.push_back(MonitorID {
- name: output.DeviceName,
- readable_name: readable_name,
- flags: output.StateFlags,
- position: position,
- dimensions: dimensions,
- });
+ for monitor in DeviceEnumerator::monitors(adapter.DeviceName.as_ptr()) {
+ // adding to the resulting list
+ result.push_back(MonitorID {
+ adapter_name: adapter.DeviceName,
+ monitor_name: wchar_as_string(monitor.DeviceName.as_slice()),
+ readable_name: wchar_as_string(monitor.DeviceString.as_slice()),
+ flags: monitor.StateFlags,
+ position: position,
+ dimensions: dimensions,
+ });
+ }
}
-
result
}
@@ -117,7 +153,7 @@ impl MonitorID {
/// See the docs of the crate root file.
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.
@@ -126,10 +162,10 @@ impl MonitorID {
self.dimensions
}
- /// This is a Win32-only function for `MonitorID` that returns the system name of the device.
- pub fn get_system_name(&self) -> &[winapi::WCHAR] {
- // TODO: retreive the position every time this is called
- self.name.as_slice()
+ /// This is a Win32-only function for `MonitorID` that returns the system name of the adapter
+ /// device.
+ pub fn get_adapter_name(&self) -> &[winapi::WCHAR] {
+ self.adapter_name.as_slice()
}
/// This is a Win32-only function for `MonitorID` that returns the position of the