aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTomaka17 <pierre.krieger1708@gmail.com>2014-07-31 10:52:05 +0200
committerTomaka17 <pierre.krieger1708@gmail.com>2014-07-31 11:13:40 +0200
commitd9d293667a7b5934ba923f578ffbfd2c12d121be (patch)
tree6ac0c7ed6bb98b8eeda249141afac0928fdd0cec /src
parentdb8955a9d85d7e44e63dd3fd7634230bc1aed635 (diff)
downloadglutin-d9d293667a7b5934ba923f578ffbfd2c12d121be.tar.gz
glutin-d9d293667a7b5934ba923f578ffbfd2c12d121be.zip
Add monitor support for win32
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs3
-rw-r--r--src/win32/ffi.rs47
-rw-r--r--src/win32/mod.rs28
-rw-r--r--src/win32/monitor.rs79
-rw-r--r--src/x11/mod.rs6
5 files changed, 150 insertions, 13 deletions
diff --git a/src/lib.rs b/src/lib.rs
index ab35774..953864a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -258,6 +258,7 @@ pub fn get_primary_monitor() -> MonitorID {
impl MonitorID {
/// Returns a human-readable name of the monitor.
pub fn get_name(&self) -> Option<String> {
- Some("<Unknown>".to_string())
+ let &MonitorID(ref id) = self;
+ id.get_name()
}
}
diff --git a/src/win32/ffi.rs b/src/win32/ffi.rs
index 268edbc..a217e20 100644
--- a/src/win32/ffi.rs
+++ b/src/win32/ffi.rs
@@ -1,6 +1,7 @@
#![allow(dead_code)]
#![allow(non_snake_case_functions)]
#![allow(non_camel_case_types)]
+#![allow(uppercase_variables)]
use libc;
@@ -136,6 +137,13 @@ pub static DISP_CHANGE_BADPARAM: LONG = -5;
pub static DISP_CHANGE_BADDUALVIEW: LONG = -6;
// ?
+pub static DISPLAY_DEVICE_ACTIVE: DWORD = 0x00000001;
+pub static DISPLAY_DEVICE_MULTI_DRIVER: DWORD = 0x00000002;
+pub static DISPLAY_DEVICE_PRIMARY_DEVICE: DWORD = 0x00000004;
+pub static DISPLAY_DEVICE_MIRRORING_DRIVER: DWORD = 0x00000008;
+pub static DISPLAY_DEVICE_VGA_COMPATIBLE: DWORD = 0x00000010;
+
+// ?
pub static DM_ORIENTATION: DWORD = 0x00000001;
pub static DM_PAPERSIZE: DWORD = 0x00000002;
pub static DM_PAPERLENGTH: DWORD = 0x00000004;
@@ -167,6 +175,13 @@ pub static DM_PANNINGWIDTH: DWORD = 0x08000000;
pub static DM_PANNINGHEIGHT: DWORD = 0x10000000;
pub static DM_DISPLAYFIXEDOUTPUT: DWORD = 0x20000000;
+// http://msdn.microsoft.com/en-us/library/windows/desktop/dd162609(v=vs.85).aspx
+pub static EDD_GET_DEVICE_INTERFACE_NAME: DWORD = 0x00000001;
+
+// ?
+pub static ENUM_CURRENT_SETTINGS: DWORD = -1;
+pub static ENUM_REGISTRY_SETTINGS: DWORD = -2;
+
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms679351(v=vs.85).aspx
pub static FORMAT_MESSAGE_ALLOCATE_BUFFER: DWORD = 0x00000100;
pub static FORMAT_MESSAGE_ARGUMENT_ARRAY: DWORD = 0x00002000;
@@ -520,6 +535,13 @@ pub struct PIXELFORMATDESCRIPTOR {
pub dwDamageMask: DWORD,
}
+// http://msdn.microsoft.com/en-us/library/dd162807(v=vs.85).aspx
+#[repr(C)]
+pub struct POINTL {
+ pub x: LONG,
+ pub y: LONG,
+}
+
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd183565(v=vs.85).aspx
#[repr(C)]
pub struct DEVMODE {
@@ -529,7 +551,7 @@ pub struct DEVMODE {
pub dmSize: WORD,
pub dmDriverExtra: WORD,
pub dmFields: DWORD,
- union1: [u8, ..16],
+ pub union1: [u8, ..16],
pub dmColor: libc::c_short,
pub dmDuplex: libc::c_short,
pub dmYResolution: libc::c_short,
@@ -563,6 +585,17 @@ pub struct WINDOWPLACEMENT {
pub rcNormalPosition: RECT,
}
+// http://msdn.microsoft.com/en-us/library/windows/desktop/dd183569(v=vs.85).aspx
+#[repr(C)]
+pub struct DISPLAY_DEVICEW {
+ pub cb: DWORD,
+ pub DeviceName: [WCHAR, ..32],
+ pub DeviceString: [WCHAR, ..128],
+ pub StateFlags: DWORD,
+ pub DeviceID: [WCHAR, ..128],
+ pub DeviceKey: [WCHAR, ..128],
+}
+
pub type LPMSG = *mut MSG;
#[link(name = "advapi32")]
@@ -590,6 +623,10 @@ extern "system" {
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd183411(v=vs.85).aspx
pub fn ChangeDisplaySettingsW(lpDevMode: *mut DEVMODE, dwFlags: DWORD) -> LONG;
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/dd183413(v=vs.85).aspx
+ pub fn ChangeDisplaySettingsExW(lpszDeviceName: LPCWSTR, lpDevMode: *mut DEVMODE, hwnd: HWND,
+ dwFlags: DWORD, lParam: LPVOID) -> LONG;
+
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms632680(v=vs.85).aspx
pub fn CreateWindowExW(dwExStyle: DWORD, lpClassName: LPCWSTR, lpWindowName: LPCWSTR,
dwStyle: DWORD, x: libc::c_int, y: libc::c_int, nWidth: libc::c_int, nHeight: libc::c_int,
@@ -611,6 +648,14 @@ extern "system" {
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd162598(v=vs.85).aspx
pub fn EndPaint(hWnd: HWND, lpPaint: *const PAINTSTRUCT) -> BOOL;
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/dd162609(v=vs.85).aspx
+ pub fn EnumDisplayDevicesW(lpDevice: LPCWSTR, iDevNum: DWORD,
+ lpDisplayDevice: *mut DISPLAY_DEVICEW, dwFlags: DWORD) -> BOOL;
+
+ // http://msdn.microsoft.com/en-us/library/dd162612(v=vs.85).aspx
+ pub fn EnumDisplaySettingsExW(lpszDeviceName: LPCWSTR, iModeNum: DWORD,
+ lpDevMode: *mut DEVMODE, dwFlags: DWORD) -> BOOL;
+
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd162719(v=vs.85).aspx
pub fn FillRect(hDC: HDC, lprc: *const RECT, hbr: HBRUSH) -> libc::c_int;
diff --git a/src/win32/mod.rs b/src/win32/mod.rs
index 232f0e5..0cb8ac9 100644
--- a/src/win32/mod.rs
+++ b/src/win32/mod.rs
@@ -4,8 +4,11 @@ use std::sync::atomics::AtomicBool;
use std::ptr;
use {Event, Hints};
+pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor};
+
mod event;
mod ffi;
+mod monitor;
pub struct Window {
window: ffi::HWND,
@@ -17,16 +20,6 @@ pub struct Window {
nosend: NoSend,
}
-pub struct MonitorID(uint);
-
-pub fn get_available_monitors() -> Vec<MonitorID> {
- unimplemented!()
-}
-
-pub fn get_primary_monitor() -> MonitorID {
- unimplemented!()
-}
-
/// Stores the list of all the windows.
/// Only available on callback thread.
local_data_key!(pub WINDOWS_LIST: Mutex<Vec<(ffi::HWND, Sender<Event>)>>)
@@ -78,6 +71,18 @@ impl Window {
// switching to fullscreen
if monitor.is_some() {
+ let monitor = monitor.as_ref().unwrap();
+
+ // adjusting the rect
+ {
+ let pos = monitor.get_position();
+ rect.left += pos.val0() as ffi::LONG;
+ rect.right += pos.val0() as ffi::LONG;
+ rect.top += pos.val1() as ffi::LONG;
+ rect.bottom += pos.val1() as ffi::LONG;
+ }
+
+ // changing device settings
let mut screen_settings: ffi::DEVMODE = unsafe { mem::zeroed() };
screen_settings.dmSize = mem::size_of::<ffi::DEVMODE>() as ffi::WORD;
screen_settings.dmPelsWidth = 1024;
@@ -85,7 +90,8 @@ impl Window {
screen_settings.dmBitsPerPel = 32;
screen_settings.dmFields = ffi::DM_BITSPERPEL | ffi::DM_PELSWIDTH | ffi::DM_PELSHEIGHT;
- let result = unsafe { ffi::ChangeDisplaySettingsW(&mut screen_settings, ffi::CDS_FULLSCREEN) };
+ let result = unsafe { ffi::ChangeDisplaySettingsExW(monitor.get_system_name().as_ptr(),
+ &mut screen_settings, ptr::mut_null(), ffi::CDS_FULLSCREEN, ptr::mut_null()) };
if result != ffi::DISP_CHANGE_SUCCESSFUL {
return Err(format!("ChangeDisplaySettings failed: {}", result))
}
diff --git a/src/win32/monitor.rs b/src/win32/monitor.rs
new file mode 100644
index 0000000..d53577e
--- /dev/null
+++ b/src/win32/monitor.rs
@@ -0,0 +1,79 @@
+use super::ffi;
+
+pub struct MonitorID {
+ name: [ffi::WCHAR, ..32],
+ readable_name: String,
+ flags: ffi::DWORD,
+ position: (uint, uint),
+}
+
+pub fn get_available_monitors() -> Vec<MonitorID> {
+ use std::{iter, mem, ptr};
+
+ let mut result = Vec::new();
+
+ for id in iter::count(0u, 1) {
+ let mut output: ffi::DISPLAY_DEVICEW = unsafe { mem::zeroed() };
+ output.cb = mem::size_of::<ffi::DISPLAY_DEVICEW>() as ffi::DWORD;
+
+ if unsafe { ffi::EnumDisplayDevicesW(ptr::null(), id as ffi::DWORD, &mut output, 0) } == 0 {
+ break
+ }
+
+ if (output.StateFlags & ffi::DISPLAY_DEVICE_ACTIVE) == 0 ||
+ (output.StateFlags & ffi::DISPLAY_DEVICE_MIRRORING_DRIVER) != 0
+ {
+ continue
+ }
+
+ let readable_name = String::from_utf16_lossy(output.DeviceString.as_slice());
+ let readable_name = readable_name.as_slice().trim_right_chars(0 as char).to_string();
+
+ let position = unsafe {
+ let mut dev: ffi::DEVMODE = mem::zeroed();
+ dev.dmSize = mem::size_of::<ffi::DEVMODE>() as ffi::WORD;
+
+ if ffi::EnumDisplaySettingsExW(output.DeviceName.as_ptr(), ffi::ENUM_CURRENT_SETTINGS,
+ &mut dev, 0) == 0
+ {
+ continue
+ }
+
+ let point: &ffi::POINTL = mem::transmute(&dev.union1);
+ (point.x as uint, point.y as uint)
+ };
+
+ result.push(MonitorID {
+ name: output.DeviceName,
+ readable_name: readable_name,
+ flags: output.StateFlags,
+ position: position,
+ });
+ }
+
+ result
+}
+
+pub fn get_primary_monitor() -> MonitorID {
+ for monitor in get_available_monitors().move_iter() {
+ if (monitor.flags & ffi::DISPLAY_DEVICE_PRIMARY_DEVICE) != 0 {
+ return monitor
+ }
+ }
+
+ fail!("Failed to find the primary monitor")
+}
+
+impl MonitorID {
+ pub fn get_name(&self) -> Option<String> {
+ Some(self.readable_name.clone())
+ }
+
+ pub fn get_system_name(&self) -> &[ffi::WCHAR] {
+ self.name.as_slice()
+ }
+
+ pub fn get_position(&self) -> (uint, uint) {
+ self.position
+ }
+}
diff --git a/src/x11/mod.rs b/src/x11/mod.rs
index 9d08d4a..61488a1 100644
--- a/src/x11/mod.rs
+++ b/src/x11/mod.rs
@@ -24,6 +24,12 @@ pub fn get_primary_monitor() -> MonitorID {
unimplemented!()
}
+impl MonitorID {
+ pub fn get_name(&self) -> Option<String> {
+ Some("<Unknown>".to_string())
+ }
+}
+
impl Window {
pub fn new(dimensions: Option<(uint, uint)>, title: &str, hints: &Hints, _: Option<MonitorID>)
-> Result<Window, String>