diff options
Diffstat (limited to 'src/win32')
-rw-r--r-- | src/win32/init.rs | 64 | ||||
-rw-r--r-- | src/win32/mod.rs | 104 | ||||
-rw-r--r-- | src/win32/monitor.rs | 28 |
3 files changed, 108 insertions, 88 deletions
diff --git a/src/win32/init.rs b/src/win32/init.rs index 3cdf8d5..7317c42 100644 --- a/src/win32/init.rs +++ b/src/win32/init.rs @@ -6,7 +6,9 @@ use {CreationError, Event}; use CreationError::OsError; use std::cell::RefCell; +use std::ffi::CString; use std::rc::Rc; +use std::sync::mpsc::{Sender, Receiver, channel}; use libc; use super::gl; @@ -18,11 +20,15 @@ use winapi; /// receive an event for another window. thread_local!(static WINDOW: Rc<RefCell<Option<(winapi::HWND, Sender<Event>)>>> = Rc::new(RefCell::new(None))); -pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: String, +/// Work-around the fact that HGLRC doesn't implement Send +pub struct ContextHack(pub winapi::HGLRC); +unsafe impl Send for ContextHack {} + +pub fn new_window(builder_dimensions: Option<(u32, u32)>, builder_title: String, builder_monitor: Option<super::MonitorID>, - builder_gl_version: Option<(uint, uint)>, builder_debug: bool, + builder_gl_version: Option<(u32, u32)>, builder_debug: bool, builder_vsync: bool, builder_hidden: bool, - builder_sharelists: Option<winapi::HGLRC>, builder_multisampling: Option<u16>) + builder_sharelists: Option<ContextHack>, builder_multisampling: Option<u16>) -> Result<Window, CreationError> { use std::mem; @@ -38,6 +44,8 @@ pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: Strin // so we create a new thread dedicated to this window. // This is the only safe method. Using `nosend` wouldn't work for non-native runtime. ::std::thread::Thread::spawn(move || { + let builder_sharelists = builder_sharelists.map(|s| s.0); + // registering the window class let class_name = { let class_name: Vec<u16> = "Window Class".utf16_units().chain(Some(0).into_iter()) @@ -132,7 +140,7 @@ pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: Strin if handle.is_null() { use std::os; tx.send(Err(OsError(format!("CreateWindowEx function failed: {}", - os::error_string(os::errno() as uint))))); + os::error_string(os::errno() as usize))))); return; } @@ -144,7 +152,7 @@ pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: Strin let hdc = unsafe { winapi::GetDC(dummy_window) }; if hdc.is_null() { tx.send(Err(OsError(format!("GetDC function failed: {}", - os::error_string(os::errno() as uint))))); + os::error_string(os::errno() as usize))))); unsafe { winapi::DestroyWindow(dummy_window); } return; } @@ -172,7 +180,7 @@ pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: Strin if pf_index == 0 { tx.send(Err(OsError(format!("ChoosePixelFormat function failed: {}", - os::error_string(os::errno() as uint))))); + os::error_string(os::errno() as usize))))); unsafe { winapi::DestroyWindow(dummy_window); } return; } @@ -181,7 +189,7 @@ pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: Strin mem::size_of::<winapi::PIXELFORMATDESCRIPTOR>() as winapi::UINT, &mut output) } == 0 { tx.send(Err(OsError(format!("DescribePixelFormat function failed: {}", - os::error_string(os::errno() as uint))))); + os::error_string(os::errno() as usize))))); unsafe { winapi::DestroyWindow(dummy_window); } return; } @@ -193,7 +201,7 @@ pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: Strin unsafe { if winapi::SetPixelFormat(dummy_hdc, 1, &pixel_format) == 0 { tx.send(Err(OsError(format!("SetPixelFormat function failed: {}", - os::error_string(os::errno() as uint))))); + os::error_string(os::errno() as usize))))); winapi::DestroyWindow(dummy_window); return; } @@ -204,7 +212,7 @@ pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: Strin let ctxt = unsafe { gl::wgl::CreateContext(dummy_hdc as *const libc::c_void) }; if ctxt.is_null() { tx.send(Err(OsError(format!("wglCreateContext function failed: {}", - os::error_string(os::errno() as uint))))); + os::error_string(os::errno() as usize))))); unsafe { winapi::DestroyWindow(dummy_window); } return; } @@ -216,11 +224,13 @@ pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: Strin // loading the extra WGL functions let extra_functions = gl::wgl_extra::Wgl::load_with(|addr| { + use libc; + + let addr = CString::from_slice(addr.as_bytes()); + let addr = addr.as_slice_with_nul().as_ptr(); + unsafe { - addr.with_c_str(|s| { - use libc; - gl::wgl::GetProcAddress(s) as *const libc::c_void - }) + gl::wgl::GetProcAddress(addr) as *const libc::c_void } }); @@ -261,7 +271,7 @@ pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: Strin if handle.is_null() { use std::os; tx.send(Err(OsError(format!("CreateWindowEx function failed: {}", - os::error_string(os::errno() as uint))))); + os::error_string(os::errno() as usize))))); return; } @@ -273,7 +283,7 @@ pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: Strin let hdc = unsafe { winapi::GetDC(real_window) }; if hdc.is_null() { tx.send(Err(OsError(format!("GetDC function failed: {}", - os::error_string(os::errno() as uint))))); + os::error_string(os::errno() as usize))))); unsafe { winapi::DestroyWindow(real_window); } return; } @@ -284,7 +294,7 @@ pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: Strin unsafe { if winapi::SetPixelFormat(hdc, 1, &pixel_format) == 0 { tx.send(Err(OsError(format!("SetPixelFormat function failed: {}", - os::error_string(os::errno() as uint))))); + os::error_string(os::errno() as usize))))); winapi::DestroyWindow(real_window); return; } @@ -329,7 +339,7 @@ pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: Strin if ctxt.is_null() { tx.send(Err(OsError(format!("OpenGL context creation failed: {}", - os::error_string(os::errno() as uint))))); + os::error_string(os::errno() as usize))))); unsafe { winapi::DestroyWindow(real_window); } return; } @@ -359,7 +369,7 @@ pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: Strin let lib = unsafe { winapi::LoadLibraryW(name) }; if lib.is_null() { tx.send(Err(OsError(format!("LoadLibrary function failed: {}", - os::error_string(os::errno() as uint))))); + os::error_string(os::errno() as usize))))); unsafe { gl::wgl::DeleteContext(context); } unsafe { winapi::DestroyWindow(real_window); } return; @@ -409,9 +419,9 @@ pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: Strin unsafe { winapi::TranslateMessage(&msg) }; unsafe { winapi::DispatchMessageW(&msg) }; // calls `callback` (see below) } - }).detach(); + }); - rx.recv() + rx.recv().unwrap() } /// Checks that the window is the good one, and if so send the event to it. @@ -429,7 +439,7 @@ fn send_event(input_window: winapi::HWND, event: Event) { return; } - sender.send_opt(event).ok(); // ignoring if closed + sender.send(event).ok(); // ignoring if closed }); } @@ -465,16 +475,16 @@ extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, winapi::WM_SIZE => { use events::Event::Resized; - let w = winapi::LOWORD(lparam as winapi::DWORD) as uint; - let h = winapi::HIWORD(lparam as winapi::DWORD) as uint; + let w = winapi::LOWORD(lparam as winapi::DWORD) as u32; + let h = winapi::HIWORD(lparam as winapi::DWORD) as u32; send_event(window, Resized(w, h)); 0 }, winapi::WM_MOVE => { use events::Event::Moved; - let x = winapi::LOWORD(lparam as winapi::DWORD) as i16 as int; - let y = winapi::HIWORD(lparam as winapi::DWORD) as i16 as int; + let x = winapi::LOWORD(lparam as winapi::DWORD) as i32; + let y = winapi::HIWORD(lparam as winapi::DWORD) as i32; send_event(window, Moved(x, y)); 0 }, @@ -490,8 +500,8 @@ extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, winapi::WM_MOUSEMOVE => { use events::Event::MouseMoved; - let x = winapi::GET_X_LPARAM(lparam) as int; - let y = winapi::GET_Y_LPARAM(lparam) as int; + let x = winapi::GET_X_LPARAM(lparam) as i32; + let y = winapi::GET_Y_LPARAM(lparam) as i32; send_event(window, MouseMoved((x, y))); diff --git a/src/win32/mod.rs b/src/win32/mod.rs index dba08e5..e6964b4 100644 --- a/src/win32/mod.rs +++ b/src/win32/mod.rs @@ -1,13 +1,12 @@ use std::sync::atomic::AtomicBool; use std::ptr; +use std::ffi::CString; +use std::collections::RingBuf; +use std::sync::mpsc::Receiver; use libc; -use {CreationError, Event}; +use {CreationError, Event, MouseCursor}; -#[cfg(feature = "window")] -use WindowBuilder; - -#[cfg(feature = "headless")] -use HeadlessRendererBuilder; +use BuilderAttribs; pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor}; @@ -18,16 +17,14 @@ mod gl; mod init; mod monitor; -/// -#[cfg(feature = "headless")] +/// pub struct HeadlessContext(Window); -#[cfg(feature = "headless")] impl HeadlessContext { /// See the docs in the crate root file. - pub fn new(builder: HeadlessRendererBuilder) -> Result<HeadlessContext, CreationError> { - let HeadlessRendererBuilder { dimensions, gl_version, gl_debug } = builder; - init::new_window(Some(dimensions), "".to_string(), None, gl_version, gl_debug, false, true, + pub fn new(builder: BuilderAttribs) -> Result<HeadlessContext, CreationError> { + let BuilderAttribs { dimensions, gl_version, gl_debug, .. } = builder; + init::new_window(dimensions, "".to_string(), None, gl_version, gl_debug, false, true, None, None) .map(|w| HeadlessContext(w)) } @@ -47,10 +44,15 @@ impl HeadlessContext { ::Api::OpenGl } - pub fn set_window_resize_callback(&mut self, _: Option<fn(uint, uint)>) { + pub fn set_window_resize_callback(&mut self, _: Option<fn(u32, u32)>) { } } +#[cfg(feature = "headless")] +unsafe impl Send for HeadlessContext {} +#[cfg(feature = "headless")] +unsafe impl Sync for HeadlessContext {} + /// The Win32 implementation of the main `Window` object. pub struct Window { /// Main handle for the window. @@ -75,18 +77,21 @@ pub struct Window { is_closed: AtomicBool, } -#[cfg(feature = "window")] +unsafe impl Send for Window {} +unsafe impl Sync for Window {} + impl Window { /// See the docs in the crate root file. - pub fn new(builder: WindowBuilder) -> Result<Window, CreationError> { - let WindowBuilder { dimensions, title, monitor, gl_version, - gl_debug, vsync, visible, sharing, multisampling } = builder; + pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> { + let BuilderAttribs { dimensions, title, monitor, gl_version, + gl_debug, vsync, visible, sharing, multisampling, .. } = builder; init::new_window(dimensions, title, monitor, gl_version, gl_debug, vsync, - !visible, sharing.map(|w| w.window.context), multisampling) + !visible, sharing.map(|w| init::ContextHack(w.context)), + multisampling) } } -#[deriving(Clone)] +#[derive(Clone)] pub struct WindowProxy; impl WindowProxy { @@ -98,12 +103,12 @@ impl WindowProxy { impl Window { /// See the docs in the crate root file. pub fn is_closed(&self) -> bool { - use std::sync::atomic::Relaxed; + use std::sync::atomic::Ordering::Relaxed; self.is_closed.load(Relaxed) } /// See the docs in the crate root file. - /// + /// /// Calls SetWindowText on the HWND. pub fn set_title(&self, text: &str) { unsafe { @@ -126,7 +131,7 @@ impl Window { } /// See the docs in the crate root file. - pub fn get_position(&self) -> Option<(int, int)> { + pub fn get_position(&self) -> Option<(i32, i32)> { use std::mem; let mut placement: winapi::WINDOWPLACEMENT = unsafe { mem::zeroed() }; @@ -137,11 +142,11 @@ impl Window { } let ref rect = placement.rcNormalPosition; - Some((rect.left as int, rect.top as int)) + Some((rect.left as i32, rect.top as i32)) } /// See the docs in the crate root file. - pub fn set_position(&self, x: int, y: int) { + pub fn set_position(&self, x: i32, y: i32) { use libc; unsafe { @@ -152,7 +157,7 @@ impl Window { } /// See the docs in the crate root file. - pub fn get_inner_size(&self) -> Option<(uint, uint)> { + pub fn get_inner_size(&self) -> Option<(u32, u32)> { use std::mem; let mut rect: winapi::RECT = unsafe { mem::uninitialized() }; @@ -161,13 +166,13 @@ impl Window { } Some(( - (rect.right - rect.left) as uint, - (rect.bottom - rect.top) as uint + (rect.right - rect.left) as u32, + (rect.bottom - rect.top) as u32 )) } /// See the docs in the crate root file. - pub fn get_outer_size(&self) -> Option<(uint, uint)> { + pub fn get_outer_size(&self) -> Option<(u32, u32)> { use std::mem; let mut rect: winapi::RECT = unsafe { mem::uninitialized() }; @@ -176,13 +181,13 @@ impl Window { } Some(( - (rect.right - rect.left) as uint, - (rect.bottom - rect.top) as uint + (rect.right - rect.left) as u32, + (rect.bottom - rect.top) as u32 )) } /// See the docs in the crate root file. - pub fn set_inner_size(&self, x: uint, y: uint) { + pub fn set_inner_size(&self, x: u32, y: u32) { use libc; unsafe { @@ -198,33 +203,33 @@ impl Window { /// See the docs in the crate root file. // TODO: return iterator - pub fn poll_events(&self) -> Vec<Event> { - let mut events = Vec::new(); + pub fn poll_events(&self) -> RingBuf<Event> { + let mut events = RingBuf::new(); loop { match self.events_receiver.try_recv() { - Ok(ev) => events.push(ev), + Ok(ev) => events.push_back(ev), Err(_) => break } } // if one of the received events is `Closed`, setting `is_closed` to true if events.iter().any(|e| match e { &::events::Event::Closed => true, _ => false }) { - use std::sync::atomic::Relaxed; + use std::sync::atomic::Ordering::Relaxed; self.is_closed.store(true, Relaxed); } - + events } /// See the docs in the crate root file. // TODO: return iterator - pub fn wait_events(&self) -> Vec<Event> { - match self.events_receiver.recv_opt() { + pub fn wait_events(&self) -> RingBuf<Event> { + match self.events_receiver.recv() { Ok(ev) => { // if the received event is `Closed`, setting `is_closed` to true match ev { ::events::Event::Closed => { - use std::sync::atomic::Relaxed; + use std::sync::atomic::Ordering::Relaxed; self.is_closed.store(true, Relaxed); }, _ => () @@ -237,9 +242,9 @@ impl Window { }, Err(_) => { - use std::sync::atomic::Relaxed; + use std::sync::atomic::Ordering::Relaxed; self.is_closed.store(true, Relaxed); - vec![] + RingBuf::new() } } } @@ -252,14 +257,13 @@ impl Window { /// See the docs in the crate root file. pub fn get_proc_address(&self, addr: &str) -> *const () { - use std::c_str::ToCStr; + let addr = CString::from_slice(addr.as_bytes()); + let addr = addr.as_slice_with_nul().as_ptr(); unsafe { - addr.with_c_str(|s| { - let p = gl::wgl::GetProcAddress(s) as *const (); - if !p.is_null() { return p; } - winapi::GetProcAddress(self.gl_library, s) as *const () - }) + let p = gl::wgl::GetProcAddress(addr) as *const (); + if !p.is_null() { return p; } + winapi::GetProcAddress(self.gl_library, addr) as *const () } } @@ -279,7 +283,11 @@ impl Window { ::Api::OpenGl } - pub fn set_window_resize_callback(&mut self, _: Option<fn(uint, uint)>) { + pub fn set_window_resize_callback(&mut self, _: Option<fn(u32, u32)>) { + } + + pub fn set_cursor(&self, cursor: MouseCursor) { + unimplemented!() } } diff --git a/src/win32/monitor.rs b/src/win32/monitor.rs index f841f1e..2078a52 100644 --- a/src/win32/monitor.rs +++ b/src/win32/monitor.rs @@ -1,9 +1,11 @@ use winapi; +use std::collections::RingBuf; + /// Win32 implementation of the main `MonitorID` object. pub struct MonitorID { /// The system name of the monitor. - name: [winapi::WCHAR, ..32], + name: [winapi::WCHAR; 32], /// Name to give to the user. readable_name: String, @@ -15,22 +17,22 @@ pub struct MonitorID { /// The position of the monitor in pixels on the desktop. /// /// A window that is positionned at these coordinates will overlap the monitor. - position: (uint, uint), + position: (u32, u32), /// The current resolution in pixels on the monitor. - dimensions: (uint, uint), + dimensions: (u32, u32), } /// Win32 implementation of the main `get_available_monitors` function. -pub fn get_available_monitors() -> Vec<MonitorID> { +pub fn get_available_monitors() -> RingBuf<MonitorID> { use std::{iter, mem, ptr}; // return value - let mut result = Vec::new(); + let mut result = RingBuf::new(); // 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(0u, 1) { + for id in iter::count(0u32, 1) { // getting the DISPLAY_DEVICEW object of the current device let output = { let mut output: winapi::DISPLAY_DEVICEW = unsafe { mem::zeroed() }; @@ -56,7 +58,7 @@ pub fn get_available_monitors() -> Vec<MonitorID> { // 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_chars(0 as char).to_string(); + let readable_name = readable_name.as_slice().trim_right_matches(0 as char).to_string(); // getting the position let (position, dimensions) = unsafe { @@ -70,15 +72,15 @@ pub fn get_available_monitors() -> Vec<MonitorID> { } let point: &winapi::POINTL = mem::transmute(&dev.union1); - let position = (point.x as uint, point.y as uint); + let position = (point.x as u32, point.y as u32); - let dimensions = (dev.dmPelsWidth as uint, dev.dmPelsHeight as uint); + let dimensions = (dev.dmPelsWidth as u32, dev.dmPelsHeight as u32); (position, dimensions) }; // adding to the resulting list - result.push(MonitorID { + result.push_back(MonitorID { name: output.DeviceName, readable_name: readable_name, flags: output.StateFlags, @@ -111,7 +113,7 @@ impl MonitorID { } /// See the docs if the crate root file. - pub fn get_dimensions(&self) -> (uint, uint) { + pub fn get_dimensions(&self) -> (u32, u32) { // TODO: retreive the dimensions every time this is called self.dimensions } @@ -123,9 +125,9 @@ impl MonitorID { } /// This is a Win32-only function for `MonitorID` that returns the position of the - /// monitor on the desktop. + /// monitor on the desktop. /// A window that is positionned at these coordinates will overlap the monitor. - pub fn get_position(&self) -> (uint, uint) { + pub fn get_position(&self) -> (u32, u32) { self.position } } |