From 3ad7f9a58429b02b11b18f6a70ac011f698b6f4b Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Fri, 24 Apr 2015 09:51:23 +0200 Subject: Create reorganization --- src/win32/callback.rs | 253 ----------------- src/win32/event.rs | 181 ------------- src/win32/gl.rs | 12 - src/win32/headless.rs | 40 --- src/win32/init.rs | 586 ---------------------------------------- src/win32/make_current_guard.rs | 52 ---- src/win32/mod.rs | 417 ---------------------------- src/win32/monitor.rs | 180 ------------ 8 files changed, 1721 deletions(-) delete mode 100644 src/win32/callback.rs delete mode 100644 src/win32/event.rs delete mode 100644 src/win32/gl.rs delete mode 100644 src/win32/headless.rs delete mode 100644 src/win32/init.rs delete mode 100644 src/win32/make_current_guard.rs delete mode 100644 src/win32/mod.rs delete mode 100644 src/win32/monitor.rs (limited to 'src/win32') diff --git a/src/win32/callback.rs b/src/win32/callback.rs deleted file mode 100644 index e852eeb..0000000 --- a/src/win32/callback.rs +++ /dev/null @@ -1,253 +0,0 @@ -use std::mem; -use std::ptr; -use std::cell::RefCell; -use std::sync::mpsc::Sender; -use std::sync::{Arc, Mutex}; - -use CursorState; -use Event; -use super::event; - -use user32; -use winapi; - -/// There's no parameters passed to the callback function, so it needs to get -/// its context (the HWND, the Sender for events, etc.) stashed in -/// a thread-local variable. -thread_local!(pub static CONTEXT_STASH: RefCell> = RefCell::new(None)); - -pub struct ThreadLocalData { - pub win: winapi::HWND, - pub sender: Sender, - pub cursor_state: Arc> -} - -/// Checks that the window is the good one, and if so send the event to it. -fn send_event(input_window: winapi::HWND, event: Event) { - CONTEXT_STASH.with(|context_stash| { - let context_stash = context_stash.borrow(); - let stored = match *context_stash { - None => return, - Some(ref v) => v - }; - - let &ThreadLocalData { ref win, ref sender, .. } = stored; - - if win != &input_window { - return; - } - - sender.send(event).ok(); // ignoring if closed - }); -} - -/// This is the callback that is called by `DispatchMessage` in the events loop. -/// -/// Returning 0 tells the Win32 API that the message has been processed. -pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, - wparam: winapi::WPARAM, lparam: winapi::LPARAM) - -> winapi::LRESULT -{ - match msg { - winapi::WM_DESTROY => { - use events::Event::Closed; - - CONTEXT_STASH.with(|context_stash| { - let context_stash = context_stash.borrow(); - let stored = match *context_stash { - None => return, - Some(ref v) => v - }; - - let &ThreadLocalData { ref win, .. } = stored; - - if win == &window { - user32::PostQuitMessage(0); - } - }); - - send_event(window, Closed); - 0 - }, - - winapi::WM_ERASEBKGND => { - 1 - }, - - winapi::WM_SIZE => { - use events::Event::Resized; - 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 i32; - let y = winapi::HIWORD(lparam as winapi::DWORD) as i32; - send_event(window, Moved(x, y)); - 0 - }, - - winapi::WM_CHAR => { - use std::mem; - use events::Event::ReceivedCharacter; - let chr: char = mem::transmute(wparam as u32); - send_event(window, ReceivedCharacter(chr)); - 0 - }, - - winapi::WM_MOUSEMOVE => { - use events::Event::MouseMoved; - - let x = winapi::GET_X_LPARAM(lparam) as i32; - let y = winapi::GET_Y_LPARAM(lparam) as i32; - - send_event(window, MouseMoved((x, y))); - - 0 - }, - - winapi::WM_MOUSEWHEEL => { - use events::Event::MouseWheel; - - let value = (wparam >> 16) as i16; - let value = value as i32; - - send_event(window, MouseWheel(value)); - - 0 - }, - - winapi::WM_KEYDOWN => { - use events::Event::KeyboardInput; - use events::ElementState::Pressed; - let scancode = ((lparam >> 16) & 0xff) as u8; - let vkey = event::vkeycode_to_element(wparam); - send_event(window, KeyboardInput(Pressed, scancode, vkey)); - 0 - }, - - winapi::WM_KEYUP => { - use events::Event::KeyboardInput; - use events::ElementState::Released; - let scancode = ((lparam >> 16) & 0xff) as u8; - let vkey = event::vkeycode_to_element(wparam); - send_event(window, KeyboardInput(Released, scancode, vkey)); - 0 - }, - - winapi::WM_LBUTTONDOWN => { - use events::Event::MouseInput; - use events::MouseButton::Left; - use events::ElementState::Pressed; - send_event(window, MouseInput(Pressed, Left)); - 0 - }, - - winapi::WM_LBUTTONUP => { - use events::Event::MouseInput; - use events::MouseButton::Left; - use events::ElementState::Released; - send_event(window, MouseInput(Released, Left)); - 0 - }, - - winapi::WM_RBUTTONDOWN => { - use events::Event::MouseInput; - use events::MouseButton::Right; - use events::ElementState::Pressed; - send_event(window, MouseInput(Pressed, Right)); - 0 - }, - - winapi::WM_RBUTTONUP => { - use events::Event::MouseInput; - use events::MouseButton::Right; - use events::ElementState::Released; - send_event(window, MouseInput(Released, Right)); - 0 - }, - - winapi::WM_MBUTTONDOWN => { - use events::Event::MouseInput; - use events::MouseButton::Middle; - use events::ElementState::Pressed; - send_event(window, MouseInput(Pressed, Middle)); - 0 - }, - - winapi::WM_MBUTTONUP => { - use events::Event::MouseInput; - use events::MouseButton::Middle; - use events::ElementState::Released; - send_event(window, MouseInput(Released, Middle)); - 0 - }, - - winapi::WM_INPUT => { - let mut data: winapi::RAWINPUT = mem::uninitialized(); - let mut data_size = mem::size_of::() as winapi::UINT; - user32::GetRawInputData(mem::transmute(lparam), winapi::RID_INPUT, - mem::transmute(&mut data), &mut data_size, - mem::size_of::() as winapi::UINT); - - if data.header.dwType == winapi::RIM_TYPEMOUSE { - let _x = data.mouse.lLastX; // FIXME: this is not always the relative movement - let _y = data.mouse.lLastY; - // TODO: - //send_event(window, Event::MouseRawMovement { x: x, y: y }); - - 0 - - } else { - user32::DefWindowProcW(window, msg, wparam, lparam) - } - }, - - winapi::WM_SETFOCUS => { - use events::Event::Focused; - send_event(window, Focused(true)); - 0 - }, - - winapi::WM_KILLFOCUS => { - use events::Event::Focused; - send_event(window, Focused(false)); - 0 - }, - - winapi::WM_SETCURSOR => { - CONTEXT_STASH.with(|context_stash| { - let cstash = context_stash.borrow(); - let cstash = cstash.as_ref(); - // there's a very bizarre borrow checker bug - // possibly related to rust-lang/rust/#23338 - let cursor_state = if let Some(cstash) = cstash { - if let Ok(cursor_state) = cstash.cursor_state.lock() { - match *cursor_state { - CursorState::Normal => { - user32::SetCursor(user32::LoadCursorW( - ptr::null_mut(), - winapi::IDC_ARROW)); - }, - CursorState::Grab | CursorState::Hide => { - user32::SetCursor(ptr::null_mut()); - } - } - } - } else { - return - }; - -// let &ThreadLocalData { ref cursor_state, .. } = stored; - }); - 0 - }, - - _ => { - user32::DefWindowProcW(window, msg, wparam, lparam) - } - } -} diff --git a/src/win32/event.rs b/src/win32/event.rs deleted file mode 100644 index 4c8f4f3..0000000 --- a/src/win32/event.rs +++ /dev/null @@ -1,181 +0,0 @@ -use events::VirtualKeyCode; -use winapi; - -pub fn vkeycode_to_element(code: winapi::WPARAM) -> Option { - match code { - //winapi::VK_LBUTTON => Some(VirtualKeyCode::Lbutton), - //winapi::VK_RBUTTON => Some(VirtualKeyCode::Rbutton), - //winapi::VK_CANCEL => Some(VirtualKeyCode::Cancel), - //winapi::VK_MBUTTON => Some(VirtualKeyCode::Mbutton), - //winapi::VK_XBUTTON1 => Some(VirtualKeyCode::Xbutton1), - //winapi::VK_XBUTTON2 => Some(VirtualKeyCode::Xbutton2), - winapi::VK_BACK => Some(VirtualKeyCode::Back), - winapi::VK_TAB => Some(VirtualKeyCode::Tab), - //winapi::VK_CLEAR => Some(VirtualKeyCode::Clear), - winapi::VK_RETURN => Some(VirtualKeyCode::Return), - //winapi::VK_SHIFT => Some(VirtualKeyCode::Shift), - //winapi::VK_CONTROL => Some(VirtualKeyCode::Control), - //winapi::VK_MENU => Some(VirtualKeyCode::Menu), - winapi::VK_PAUSE => Some(VirtualKeyCode::Pause), - winapi::VK_CAPITAL => Some(VirtualKeyCode::Capital), - winapi::VK_KANA => Some(VirtualKeyCode::Kana), - //winapi::VK_HANGUEL => Some(VirtualKeyCode::Hanguel), - //winapi::VK_HANGUL => Some(VirtualKeyCode::Hangul), - //winapi::VK_JUNJA => Some(VirtualKeyCode::Junja), - //winapi::VK_FINAL => Some(VirtualKeyCode::Final), - //winapi::VK_HANJA => Some(VirtualKeyCode::Hanja), - winapi::VK_KANJI => Some(VirtualKeyCode::Kanji), - winapi::VK_ESCAPE => Some(VirtualKeyCode::Escape), - winapi::VK_CONVERT => Some(VirtualKeyCode::Convert), - //winapi::VK_NONCONVERT => Some(VirtualKeyCode::Nonconvert), - //winapi::VK_ACCEPT => Some(VirtualKeyCode::Accept), - //winapi::VK_MODECHANGE => Some(VirtualKeyCode::Modechange), - winapi::VK_SPACE => Some(VirtualKeyCode::Space), - winapi::VK_PRIOR => Some(VirtualKeyCode::PageUp), - winapi::VK_NEXT => Some(VirtualKeyCode::PageDown), - winapi::VK_END => Some(VirtualKeyCode::End), - winapi::VK_HOME => Some(VirtualKeyCode::Home), - winapi::VK_LEFT => Some(VirtualKeyCode::Left), - winapi::VK_UP => Some(VirtualKeyCode::Up), - winapi::VK_RIGHT => Some(VirtualKeyCode::Right), - winapi::VK_DOWN => Some(VirtualKeyCode::Down), - //winapi::VK_SELECT => Some(VirtualKeyCode::Select), - //winapi::VK_PRINT => Some(VirtualKeyCode::Print), - //winapi::VK_EXECUTE => Some(VirtualKeyCode::Execute), - winapi::VK_SNAPSHOT => Some(VirtualKeyCode::Snapshot), - winapi::VK_INSERT => Some(VirtualKeyCode::Insert), - winapi::VK_DELETE => Some(VirtualKeyCode::Delete), - //winapi::VK_HELP => Some(VirtualKeyCode::Help), - 0x30 => Some(VirtualKeyCode::Key0), - 0x31 => Some(VirtualKeyCode::Key1), - 0x32 => Some(VirtualKeyCode::Key2), - 0x33 => Some(VirtualKeyCode::Key3), - 0x34 => Some(VirtualKeyCode::Key4), - 0x35 => Some(VirtualKeyCode::Key5), - 0x36 => Some(VirtualKeyCode::Key6), - 0x37 => Some(VirtualKeyCode::Key7), - 0x38 => Some(VirtualKeyCode::Key8), - 0x39 => Some(VirtualKeyCode::Key9), - 0x41 => Some(VirtualKeyCode::A), - 0x42 => Some(VirtualKeyCode::B), - 0x43 => Some(VirtualKeyCode::C), - 0x44 => Some(VirtualKeyCode::D), - 0x45 => Some(VirtualKeyCode::E), - 0x46 => Some(VirtualKeyCode::F), - 0x47 => Some(VirtualKeyCode::G), - 0x48 => Some(VirtualKeyCode::H), - 0x49 => Some(VirtualKeyCode::I), - 0x4A => Some(VirtualKeyCode::J), - 0x4B => Some(VirtualKeyCode::K), - 0x4C => Some(VirtualKeyCode::L), - 0x4D => Some(VirtualKeyCode::M), - 0x4E => Some(VirtualKeyCode::N), - 0x4F => Some(VirtualKeyCode::O), - 0x50 => Some(VirtualKeyCode::P), - 0x51 => Some(VirtualKeyCode::Q), - 0x52 => Some(VirtualKeyCode::R), - 0x53 => Some(VirtualKeyCode::S), - 0x54 => Some(VirtualKeyCode::T), - 0x55 => Some(VirtualKeyCode::U), - 0x56 => Some(VirtualKeyCode::V), - 0x57 => Some(VirtualKeyCode::W), - 0x58 => Some(VirtualKeyCode::X), - 0x59 => Some(VirtualKeyCode::Y), - 0x5A => Some(VirtualKeyCode::Z), - //winapi::VK_LWIN => Some(VirtualKeyCode::Lwin), - //winapi::VK_RWIN => Some(VirtualKeyCode::Rwin), - winapi::VK_APPS => Some(VirtualKeyCode::Apps), - winapi::VK_SLEEP => Some(VirtualKeyCode::Sleep), - winapi::VK_NUMPAD0 => Some(VirtualKeyCode::Numpad0), - winapi::VK_NUMPAD1 => Some(VirtualKeyCode::Numpad1), - winapi::VK_NUMPAD2 => Some(VirtualKeyCode::Numpad2), - winapi::VK_NUMPAD3 => Some(VirtualKeyCode::Numpad3), - winapi::VK_NUMPAD4 => Some(VirtualKeyCode::Numpad4), - winapi::VK_NUMPAD5 => Some(VirtualKeyCode::Numpad5), - winapi::VK_NUMPAD6 => Some(VirtualKeyCode::Numpad6), - winapi::VK_NUMPAD7 => Some(VirtualKeyCode::Numpad7), - winapi::VK_NUMPAD8 => Some(VirtualKeyCode::Numpad8), - winapi::VK_NUMPAD9 => Some(VirtualKeyCode::Numpad9), - winapi::VK_MULTIPLY => Some(VirtualKeyCode::Multiply), - winapi::VK_ADD => Some(VirtualKeyCode::Add), - //winapi::VK_SEPARATOR => Some(VirtualKeyCode::Separator), - winapi::VK_SUBTRACT => Some(VirtualKeyCode::Subtract), - winapi::VK_DECIMAL => Some(VirtualKeyCode::Decimal), - winapi::VK_DIVIDE => Some(VirtualKeyCode::Divide), - winapi::VK_F1 => Some(VirtualKeyCode::F1), - winapi::VK_F2 => Some(VirtualKeyCode::F2), - winapi::VK_F3 => Some(VirtualKeyCode::F3), - winapi::VK_F4 => Some(VirtualKeyCode::F4), - winapi::VK_F5 => Some(VirtualKeyCode::F5), - winapi::VK_F6 => Some(VirtualKeyCode::F6), - winapi::VK_F7 => Some(VirtualKeyCode::F7), - winapi::VK_F8 => Some(VirtualKeyCode::F8), - winapi::VK_F9 => Some(VirtualKeyCode::F9), - winapi::VK_F10 => Some(VirtualKeyCode::F10), - winapi::VK_F11 => Some(VirtualKeyCode::F11), - winapi::VK_F12 => Some(VirtualKeyCode::F12), - winapi::VK_F13 => Some(VirtualKeyCode::F13), - winapi::VK_F14 => Some(VirtualKeyCode::F14), - winapi::VK_F15 => Some(VirtualKeyCode::F15), - /*winapi::VK_F16 => Some(VirtualKeyCode::F16), - winapi::VK_F17 => Some(VirtualKeyCode::F17), - winapi::VK_F18 => Some(VirtualKeyCode::F18), - winapi::VK_F19 => Some(VirtualKeyCode::F19), - winapi::VK_F20 => Some(VirtualKeyCode::F20), - winapi::VK_F21 => Some(VirtualKeyCode::F21), - winapi::VK_F22 => Some(VirtualKeyCode::F22), - winapi::VK_F23 => Some(VirtualKeyCode::F23), - winapi::VK_F24 => Some(VirtualKeyCode::F24),*/ - winapi::VK_NUMLOCK => Some(VirtualKeyCode::Numlock), - winapi::VK_SCROLL => Some(VirtualKeyCode::Scroll), - /*winapi::VK_LSHIFT => Some(VirtualKeyCode::Lshift), - winapi::VK_RSHIFT => Some(VirtualKeyCode::Rshift), - winapi::VK_LCONTROL => Some(VirtualKeyCode::Lcontrol), - winapi::VK_RCONTROL => Some(VirtualKeyCode::Rcontrol), - winapi::VK_LMENU => Some(VirtualKeyCode::Lmenu), - winapi::VK_RMENU => Some(VirtualKeyCode::Rmenu), - winapi::VK_BROWSER_BACK => Some(VirtualKeyCode::Browser_back), - winapi::VK_BROWSER_FORWARD => Some(VirtualKeyCode::Browser_forward), - winapi::VK_BROWSER_REFRESH => Some(VirtualKeyCode::Browser_refresh), - winapi::VK_BROWSER_STOP => Some(VirtualKeyCode::Browser_stop), - winapi::VK_BROWSER_SEARCH => Some(VirtualKeyCode::Browser_search), - winapi::VK_BROWSER_FAVORITES => Some(VirtualKeyCode::Browser_favorites), - winapi::VK_BROWSER_HOME => Some(VirtualKeyCode::Browser_home), - winapi::VK_VOLUME_MUTE => Some(VirtualKeyCode::Volume_mute), - winapi::VK_VOLUME_DOWN => Some(VirtualKeyCode::Volume_down), - winapi::VK_VOLUME_UP => Some(VirtualKeyCode::Volume_up), - winapi::VK_MEDIA_NEXT_TRACK => Some(VirtualKeyCode::Media_next_track), - winapi::VK_MEDIA_PREV_TRACK => Some(VirtualKeyCode::Media_prev_track), - winapi::VK_MEDIA_STOP => Some(VirtualKeyCode::Media_stop), - winapi::VK_MEDIA_PLAY_PAUSE => Some(VirtualKeyCode::Media_play_pause), - winapi::VK_LAUNCH_MAIL => Some(VirtualKeyCode::Launch_mail), - winapi::VK_LAUNCH_MEDIA_SELECT => Some(VirtualKeyCode::Launch_media_select), - winapi::VK_LAUNCH_APP1 => Some(VirtualKeyCode::Launch_app1), - winapi::VK_LAUNCH_APP2 => Some(VirtualKeyCode::Launch_app2), - winapi::VK_OEM_1 => Some(VirtualKeyCode::Oem_1), - winapi::VK_OEM_PLUS => Some(VirtualKeyCode::Oem_plus), - winapi::VK_OEM_COMMA => Some(VirtualKeyCode::Oem_comma), - winapi::VK_OEM_MINUS => Some(VirtualKeyCode::Oem_minus), - winapi::VK_OEM_PERIOD => Some(VirtualKeyCode::Oem_period), - winapi::VK_OEM_2 => Some(VirtualKeyCode::Oem_2), - winapi::VK_OEM_3 => Some(VirtualKeyCode::Oem_3), - winapi::VK_OEM_4 => Some(VirtualKeyCode::Oem_4), - winapi::VK_OEM_5 => Some(VirtualKeyCode::Oem_5), - winapi::VK_OEM_6 => Some(VirtualKeyCode::Oem_6), - winapi::VK_OEM_7 => Some(VirtualKeyCode::Oem_7), - winapi::VK_OEM_8 => Some(VirtualKeyCode::Oem_8), - winapi::VK_OEM_102 => Some(VirtualKeyCode::Oem_102), - winapi::VK_PROCESSKEY => Some(VirtualKeyCode::Processkey), - winapi::VK_PACKET => Some(VirtualKeyCode::Packet), - winapi::VK_ATTN => Some(VirtualKeyCode::Attn), - winapi::VK_CRSEL => Some(VirtualKeyCode::Crsel), - winapi::VK_EXSEL => Some(VirtualKeyCode::Exsel), - winapi::VK_EREOF => Some(VirtualKeyCode::Ereof), - winapi::VK_PLAY => Some(VirtualKeyCode::Play), - winapi::VK_ZOOM => Some(VirtualKeyCode::Zoom), - winapi::VK_NONAME => Some(VirtualKeyCode::Noname), - winapi::VK_PA1 => Some(VirtualKeyCode::Pa1), - winapi::VK_OEM_CLEAR => Some(VirtualKeyCode::Oem_clear),*/ - _ => None - } -} diff --git a/src/win32/gl.rs b/src/win32/gl.rs deleted file mode 100644 index 1354d95..0000000 --- a/src/win32/gl.rs +++ /dev/null @@ -1,12 +0,0 @@ -/// WGL bindings -pub mod wgl { - include!(concat!(env!("OUT_DIR"), "/wgl_bindings.rs")); -} - -/// Functions that are not necessarly always available -pub mod wgl_extra { - include!(concat!(env!("OUT_DIR"), "/wgl_extra_bindings.rs")); -} - -#[link(name = "opengl32")] -extern {} diff --git a/src/win32/headless.rs b/src/win32/headless.rs deleted file mode 100644 index 6189360..0000000 --- a/src/win32/headless.rs +++ /dev/null @@ -1,40 +0,0 @@ -use super::Window; -use super::init; - -use Api; -use BuilderAttribs; -use CreationError; - -/// -pub struct HeadlessContext(Window); - -impl HeadlessContext { - /// See the docs in the crate root file. - pub fn new(builder: BuilderAttribs) -> Result { - let (builder, _) = builder.extract_non_static(); - init::new_window(builder, None).map(|w| HeadlessContext(w)) - } - - /// See the docs in the crate root file. - pub unsafe fn make_current(&self) { - self.0.make_current() - } - - /// See the docs in the crate root file. - pub fn is_current(&self) -> bool { - self.0.is_current() - } - - /// See the docs in the crate root file. - pub fn get_proc_address(&self, addr: &str) -> *const () { - self.0.get_proc_address(addr) - } - - /// See the docs in the crate root file. - pub fn get_api(&self) -> Api { - Api::OpenGl - } - - pub fn set_window_resize_callback(&mut self, _: Option) { - } -} diff --git a/src/win32/init.rs b/src/win32/init.rs deleted file mode 100644 index 5cdd6b8..0000000 --- a/src/win32/init.rs +++ /dev/null @@ -1,586 +0,0 @@ -use std::sync::atomic::AtomicBool; -use std::sync::{Arc, Mutex}; -use std::io; -use std::ptr; -use std::mem; -use std::thread; - -use super::callback; -use super::Window; -use super::MonitorID; -use super::ContextWrapper; -use super::WindowWrapper; -use super::make_current_guard::CurrentContextGuard; - -use Api; -use BuilderAttribs; -use CreationError; -use CreationError::OsError; -use CursorState; -use GlRequest; -use PixelFormat; - -use std::ffi::{CStr, CString, OsStr}; -use std::os::windows::ffi::OsStrExt; -use std::sync::mpsc::channel; - -use libc; -use super::gl; -use winapi; -use kernel32; -use user32; -use gdi32; - -/// 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: BuilderAttribs<'static>, builder_sharelists: Option) - -> Result -{ - // initializing variables to be sent to the task - - let title = OsStr::new(&builder.title).encode_wide().chain(Some(0).into_iter()) - .collect::>(); - - let (tx, rx) = channel(); - - // `GetMessage` must be called in the same thread as CreateWindow, so we create a new thread - // dedicated to this window. - thread::spawn(move || { - unsafe { - // creating and sending the `Window` - match init(title, builder, builder_sharelists) { - Ok(w) => tx.send(Ok(w)).ok(), - Err(e) => { - tx.send(Err(e)).ok(); - return; - } - }; - - // now that the `Window` struct is initialized, the main `Window::new()` function will - // return and this events loop will run in parallel - loop { - let mut msg = mem::uninitialized(); - - if user32::GetMessageW(&mut msg, ptr::null_mut(), 0, 0) == 0 { - break; - } - - user32::TranslateMessage(&msg); - user32::DispatchMessageW(&msg); // calls `callback` (see the callback module) - } - } - }); - - rx.recv().unwrap() -} - -unsafe fn init(title: Vec, builder: BuilderAttribs<'static>, - builder_sharelists: Option) -> Result -{ - let builder_sharelists = builder_sharelists.map(|s| s.0); - - // registering the window class - let class_name = register_window_class(); - - // building a RECT object with coordinates - let mut rect = winapi::RECT { - left: 0, right: builder.dimensions.unwrap_or((1024, 768)).0 as winapi::LONG, - top: 0, bottom: builder.dimensions.unwrap_or((1024, 768)).1 as winapi::LONG, - }; - - // switching to fullscreen if necessary - // this means adjusting the window's position so that it overlaps the right monitor, - // and change the monitor's resolution if necessary - if builder.monitor.is_some() { - let monitor = builder.monitor.as_ref().unwrap(); - try!(switch_to_fullscreen(&mut rect, monitor)); - } - - // computing the style and extended style of the window - let (ex_style, style) = if builder.monitor.is_some() { - (winapi::WS_EX_APPWINDOW, winapi::WS_POPUP | winapi::WS_CLIPSIBLINGS | winapi::WS_CLIPCHILDREN) - } else { - (winapi::WS_EX_APPWINDOW | winapi::WS_EX_WINDOWEDGE, - winapi::WS_OVERLAPPEDWINDOW | winapi::WS_CLIPSIBLINGS | winapi::WS_CLIPCHILDREN) - }; - - // adjusting the window coordinates using the style - user32::AdjustWindowRectEx(&mut rect, style, 0, ex_style); - - // the first step is to create a dummy window and a dummy context which we will use - // to load the pointers to some functions in the OpenGL driver in `extra_functions` - let extra_functions = { - // creating a dummy invisible window - let dummy_window = { - let handle = user32::CreateWindowExW(ex_style, class_name.as_ptr(), - title.as_ptr() as winapi::LPCWSTR, - style | winapi::WS_CLIPSIBLINGS | winapi::WS_CLIPCHILDREN, - winapi::CW_USEDEFAULT, winapi::CW_USEDEFAULT, - rect.right - rect.left, rect.bottom - rect.top, - ptr::null_mut(), ptr::null_mut(), kernel32::GetModuleHandleW(ptr::null()), - ptr::null_mut()); - - if handle.is_null() { - return Err(OsError(format!("CreateWindowEx function failed: {}", - format!("{}", io::Error::last_os_error())))); - } - - let hdc = user32::GetDC(handle); - if hdc.is_null() { - let err = Err(OsError(format!("GetDC function failed: {}", - format!("{}", io::Error::last_os_error())))); - return err; - } - - WindowWrapper(handle, hdc) - }; - - // getting the pixel format that we will use and setting it - { - let formats = enumerate_native_pixel_formats(&dummy_window); - let id = try!(choose_dummy_pixel_format(formats.into_iter())); - try!(set_pixel_format(&dummy_window, id)); - } - - // creating the dummy OpenGL context and making it current - let dummy_context = try!(create_context(None, &dummy_window, None)); - let current_context = try!(CurrentContextGuard::make_current(&dummy_window, - &dummy_context)); - - // loading the extra WGL functions - gl::wgl_extra::Wgl::load_with(|addr| { - use libc; - - let addr = CString::new(addr.as_bytes()).unwrap(); - let addr = addr.as_ptr(); - - gl::wgl::GetProcAddress(addr) as *const libc::c_void - }) - }; - - // creating the real window this time, by using the functions in `extra_functions` - let real_window = { - let (width, height) = if builder.monitor.is_some() || builder.dimensions.is_some() { - (Some(rect.right - rect.left), Some(rect.bottom - rect.top)) - } else { - (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 { - style | winapi::WS_VISIBLE - }; - - let handle = user32::CreateWindowExW(ex_style, class_name.as_ptr(), - title.as_ptr() as winapi::LPCWSTR, - style | winapi::WS_CLIPSIBLINGS | winapi::WS_CLIPCHILDREN, - 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()); - - if handle.is_null() { - return Err(OsError(format!("CreateWindowEx function failed: {}", - format!("{}", io::Error::last_os_error())))); - } - - let hdc = user32::GetDC(handle); - if hdc.is_null() { - return Err(OsError(format!("GetDC function failed: {}", - format!("{}", io::Error::last_os_error())))); - } - - WindowWrapper(handle, hdc) - }; - - // calling SetPixelFormat - let pixel_format = { - let formats = if extra_functions.GetPixelFormatAttribivARB.is_loaded() { - enumerate_arb_pixel_formats(&extra_functions, &real_window) - } else { - enumerate_native_pixel_formats(&real_window) - }; - - let (id, f) = try!(builder.choose_pixel_format(formats.into_iter().map(|(a, b)| (b, a)))); - try!(set_pixel_format(&real_window, id)); - f - }; - - // creating the OpenGL context - let context = try!(create_context(Some((&extra_functions, &builder)), &real_window, - builder_sharelists)); - - // calling SetForegroundWindow if fullscreen - if builder.monitor.is_some() { - user32::SetForegroundWindow(real_window.0); - } - - // Creating a mutex to track the current cursor state - let cursor_state = Arc::new(Mutex::new(CursorState::Normal)); - - // filling the CONTEXT_STASH task-local storage so that we can start receiving events - let events_receiver = { - let (tx, rx) = channel(); - let mut tx = Some(tx); - callback::CONTEXT_STASH.with(|context_stash| { - let data = callback::ThreadLocalData { - win: real_window.0, - sender: tx.take().unwrap(), - cursor_state: cursor_state.clone() - }; - (*context_stash.borrow_mut()) = Some(data); - }); - rx - }; - - // loading the opengl32 module - let gl_library = try!(load_opengl32_dll()); - - // handling vsync - if builder.vsync { - if extra_functions.SwapIntervalEXT.is_loaded() { - let _guard = try!(CurrentContextGuard::make_current(&real_window, &context)); - - if extra_functions.SwapIntervalEXT(1) == 0 { - return Err(OsError(format!("wglSwapIntervalEXT failed"))); - } - } - } - - // building the struct - Ok(Window { - window: real_window, - context: context, - gl_library: gl_library, - events_receiver: events_receiver, - is_closed: AtomicBool::new(false), - cursor_state: cursor_state, - pixel_format: pixel_format, - }) -} - -unsafe fn register_window_class() -> Vec { - let class_name = OsStr::new("Window Class").encode_wide().chain(Some(0).into_iter()) - .collect::>(); - - let class = winapi::WNDCLASSEXW { - cbSize: mem::size_of::() as winapi::UINT, - style: winapi::CS_HREDRAW | winapi::CS_VREDRAW | winapi::CS_OWNDC, - lpfnWndProc: Some(callback::callback), - cbClsExtra: 0, - cbWndExtra: 0, - hInstance: kernel32::GetModuleHandleW(ptr::null()), - hIcon: ptr::null_mut(), - hCursor: ptr::null_mut(), // must be null in order for cursor state to work properly - hbrBackground: ptr::null_mut(), - lpszMenuName: ptr::null(), - lpszClassName: class_name.as_ptr(), - hIconSm: ptr::null_mut(), - }; - - // We ignore errors because registering the same window class twice would trigger - // an error, and because errors here are detected during CreateWindowEx anyway. - // Also since there is no weird element in the struct, there is no reason for this - // call to fail. - user32::RegisterClassExW(&class); - - class_name -} - -unsafe fn switch_to_fullscreen(rect: &mut winapi::RECT, monitor: &MonitorID) - -> Result<(), CreationError> -{ - // adjusting the rect - { - let pos = monitor.get_position(); - rect.left += pos.0 as winapi::LONG; - rect.right += pos.0 as winapi::LONG; - rect.top += pos.1 as winapi::LONG; - rect.bottom += pos.1 as winapi::LONG; - } - - // changing device settings - let mut screen_settings: winapi::DEVMODEW = mem::zeroed(); - screen_settings.dmSize = mem::size_of::() as winapi::WORD; - screen_settings.dmPelsWidth = (rect.right - rect.left) as winapi::DWORD; - screen_settings.dmPelsHeight = (rect.bottom - rect.top) as winapi::DWORD; - screen_settings.dmBitsPerPel = 32; // TODO: ? - screen_settings.dmFields = winapi::DM_BITSPERPEL | winapi::DM_PELSWIDTH | winapi::DM_PELSHEIGHT; - - let result = user32::ChangeDisplaySettingsExW(monitor.get_adapter_name().as_ptr(), - &mut screen_settings, ptr::null_mut(), - winapi::CDS_FULLSCREEN, ptr::null_mut()); - - if result != winapi::DISP_CHANGE_SUCCESSFUL { - return Err(OsError(format!("ChangeDisplaySettings failed: {}", result))); - } - - Ok(()) -} - -unsafe fn create_context(extra: Option<(&gl::wgl_extra::Wgl, &BuilderAttribs<'static>)>, - hdc: &WindowWrapper, share: Option) - -> Result -{ - let share = share.unwrap_or(ptr::null_mut()); - - let ctxt = if let Some((extra_functions, builder)) = extra { - if extra_functions.CreateContextAttribsARB.is_loaded() { - let mut attributes = Vec::new(); - - match builder.gl_version { - GlRequest::Latest => {}, - GlRequest::Specific(Api::OpenGl, (major, minor)) => { - attributes.push(gl::wgl_extra::CONTEXT_MAJOR_VERSION_ARB as libc::c_int); - attributes.push(major as libc::c_int); - attributes.push(gl::wgl_extra::CONTEXT_MINOR_VERSION_ARB as libc::c_int); - attributes.push(minor as libc::c_int); - }, - GlRequest::Specific(Api::OpenGlEs, (major, minor)) => { - if is_extension_supported(extra_functions, hdc, - "WGL_EXT_create_context_es2_profile") - { - attributes.push(gl::wgl_extra::CONTEXT_PROFILE_MASK_ARB as libc::c_int); - attributes.push(gl::wgl_extra::CONTEXT_ES2_PROFILE_BIT_EXT as libc::c_int); - } else { - return Err(CreationError::NotSupported); - } - - attributes.push(gl::wgl_extra::CONTEXT_MAJOR_VERSION_ARB as libc::c_int); - attributes.push(major as libc::c_int); - attributes.push(gl::wgl_extra::CONTEXT_MINOR_VERSION_ARB as libc::c_int); - attributes.push(minor as libc::c_int); - }, - GlRequest::Specific(_, _) => return Err(CreationError::NotSupported), - GlRequest::GlThenGles { opengl_version: (major, minor), .. } => { - attributes.push(gl::wgl_extra::CONTEXT_MAJOR_VERSION_ARB as libc::c_int); - attributes.push(major as libc::c_int); - attributes.push(gl::wgl_extra::CONTEXT_MINOR_VERSION_ARB as libc::c_int); - attributes.push(minor as libc::c_int); - }, - } - - if builder.gl_debug { - attributes.push(gl::wgl_extra::CONTEXT_FLAGS_ARB as libc::c_int); - attributes.push(gl::wgl_extra::CONTEXT_DEBUG_BIT_ARB as libc::c_int); - } - - attributes.push(0); - - Some(extra_functions.CreateContextAttribsARB(hdc.1 as *const libc::c_void, - share as *const libc::c_void, - attributes.as_ptr())) - - } else { - None - } - } else { - None - }; - - let ctxt = match ctxt { - Some(ctxt) => ctxt, - None => { - let ctxt = gl::wgl::CreateContext(hdc.1 as *const libc::c_void); - if !ctxt.is_null() && !share.is_null() { - gl::wgl::ShareLists(share as *const libc::c_void, ctxt); - }; - ctxt - } - }; - - if ctxt.is_null() { - return Err(OsError(format!("OpenGL context creation failed: {}", - format!("{}", io::Error::last_os_error())))); - } - - Ok(ContextWrapper(ctxt as winapi::HGLRC)) -} - -unsafe fn enumerate_native_pixel_formats(hdc: &WindowWrapper) -> Vec<(PixelFormat, libc::c_int)> { - let size_of_pxfmtdescr = mem::size_of::() as u32; - let num = gdi32::DescribePixelFormat(hdc.1, 1, size_of_pxfmtdescr, ptr::null_mut()); - - let mut result = Vec::new(); - - for index in (0 .. num) { - let mut output: winapi::PIXELFORMATDESCRIPTOR = mem::zeroed(); - - if gdi32::DescribePixelFormat(hdc.1, index, size_of_pxfmtdescr, &mut output) == 0 { - continue; - } - - if (output.dwFlags & winapi::PFD_DRAW_TO_WINDOW) == 0 { - continue; - } - - if (output.dwFlags & winapi::PFD_SUPPORT_OPENGL) == 0 { - continue; - } - - if output.iPixelType != winapi::PFD_TYPE_RGBA { - continue; - } - - result.push((PixelFormat { - hardware_accelerated: (output.dwFlags & winapi::PFD_GENERIC_FORMAT) == 0, - red_bits: output.cRedBits, - green_bits: output.cGreenBits, - blue_bits: output.cBlueBits, - alpha_bits: output.cAlphaBits, - depth_bits: output.cDepthBits, - stencil_bits: output.cStencilBits, - stereoscopy: (output.dwFlags & winapi::PFD_STEREO) != 0, - double_buffer: (output.dwFlags & winapi::PFD_DOUBLEBUFFER) != 0, - multisampling: None, - srgb: false, - }, index)); - } - - result -} - -unsafe fn enumerate_arb_pixel_formats(extra: &gl::wgl_extra::Wgl, hdc: &WindowWrapper) - -> Vec<(PixelFormat, libc::c_int)> -{ - let get_info = |index: u32, attrib: u32| { - let mut value = mem::uninitialized(); - extra.GetPixelFormatAttribivARB(hdc.1 as *const libc::c_void, index as libc::c_int, - 0, 1, [attrib as libc::c_int].as_ptr(), - &mut value); - value as u32 - }; - - // getting the number of formats - // the `1` is ignored - let num = get_info(1, gl::wgl_extra::NUMBER_PIXEL_FORMATS_ARB); - - let mut result = Vec::new(); - - for index in (0 .. num) { - if get_info(index, gl::wgl_extra::DRAW_TO_WINDOW_ARB) == 0 { - continue; - } - if get_info(index, gl::wgl_extra::SUPPORT_OPENGL_ARB) == 0 { - continue; - } - - if get_info(index, gl::wgl_extra::ACCELERATION_ARB) == gl::wgl_extra::NO_ACCELERATION_ARB { - continue; - } - - if get_info(index, gl::wgl_extra::PIXEL_TYPE_ARB) != gl::wgl_extra::TYPE_RGBA_ARB { - continue; - } - - result.push((PixelFormat { - hardware_accelerated: true, - red_bits: get_info(index, gl::wgl_extra::RED_BITS_ARB) as u8, - green_bits: get_info(index, gl::wgl_extra::GREEN_BITS_ARB) as u8, - blue_bits: get_info(index, gl::wgl_extra::BLUE_BITS_ARB) as u8, - alpha_bits: get_info(index, gl::wgl_extra::ALPHA_BITS_ARB) as u8, - depth_bits: get_info(index, gl::wgl_extra::DEPTH_BITS_ARB) as u8, - stencil_bits: get_info(index, gl::wgl_extra::STENCIL_BITS_ARB) as u8, - stereoscopy: get_info(index, gl::wgl_extra::STEREO_ARB) != 0, - double_buffer: get_info(index, gl::wgl_extra::DOUBLE_BUFFER_ARB) != 0, - multisampling: { - if is_extension_supported(extra, hdc, "WGL_ARB_multisample") { - match get_info(index, gl::wgl_extra::SAMPLES_ARB) { - 0 => None, - a => Some(a as u16), - } - } else { - None - } - }, - srgb: if is_extension_supported(extra, hdc, "WGL_ARB_framebuffer_sRGB") { - get_info(index, gl::wgl_extra::FRAMEBUFFER_SRGB_CAPABLE_ARB) != 0 - } else if is_extension_supported(extra, hdc, "WGL_EXT_framebuffer_sRGB") { - get_info(index, gl::wgl_extra::FRAMEBUFFER_SRGB_CAPABLE_EXT) != 0 - } else { - false - }, - }, index as libc::c_int)); - } - - result -} - -unsafe fn set_pixel_format(hdc: &WindowWrapper, id: libc::c_int) -> Result<(), CreationError> { - let mut output: winapi::PIXELFORMATDESCRIPTOR = mem::zeroed(); - - if gdi32::DescribePixelFormat(hdc.1, id, mem::size_of::() - as winapi::UINT, &mut output) == 0 - { - return Err(OsError(format!("DescribePixelFormat function failed: {}", - format!("{}", io::Error::last_os_error())))); - } - - if gdi32::SetPixelFormat(hdc.1, id, &output) == 0 { - return Err(OsError(format!("SetPixelFormat function failed: {}", - format!("{}", io::Error::last_os_error())))); - } - - Ok(()) -} - -unsafe fn load_opengl32_dll() -> Result { - let name = OsStr::new("opengl32.dll").encode_wide().chain(Some(0).into_iter()) - .collect::>(); - - let lib = kernel32::LoadLibraryW(name.as_ptr()); - - if lib.is_null() { - return Err(OsError(format!("LoadLibrary function failed: {}", - format!("{}", io::Error::last_os_error())))); - } - - Ok(lib) -} - -unsafe fn is_extension_supported(extra: &gl::wgl_extra::Wgl, hdc: &WindowWrapper, - extension: &str) -> bool -{ - let extensions = if extra.GetExtensionsStringARB.is_loaded() { - let data = extra.GetExtensionsStringARB(hdc.1 as *const _); - let data = CStr::from_ptr(data).to_bytes().to_vec(); - String::from_utf8(data).unwrap() - - } else if extra.GetExtensionsStringEXT.is_loaded() { - let data = extra.GetExtensionsStringEXT(); - let data = CStr::from_ptr(data).to_bytes().to_vec(); - String::from_utf8(data).unwrap() - - } else { - return false; - }; - - extensions.split(" ").find(|&e| e == extension).is_some() -} - -fn choose_dummy_pixel_format(iter: I) -> Result - where I: Iterator -{ - let mut backup_id = None; - - for (format, id) in iter { - if backup_id.is_none() { - backup_id = Some(id); - } - - if format.hardware_accelerated { - return Ok(id); - } - } - - backup_id.ok_or(CreationError::NotSupported) -} diff --git a/src/win32/make_current_guard.rs b/src/win32/make_current_guard.rs deleted file mode 100644 index 8983899..0000000 --- a/src/win32/make_current_guard.rs +++ /dev/null @@ -1,52 +0,0 @@ -use std::marker::PhantomData; -use std::io; - -use libc; -use winapi; -use CreationError; - -use super::gl; -use super::ContextWrapper; -use super::WindowWrapper; - -/// A guard for when you want to make the context current. Destroying the guard restores the -/// previously-current context. -pub struct CurrentContextGuard<'a, 'b> { - previous_hdc: winapi::HDC, - previous_hglrc: winapi::HGLRC, - marker1: PhantomData<&'a ()>, - marker2: PhantomData<&'b ()>, -} - -impl<'a, 'b> CurrentContextGuard<'a, 'b> { - pub unsafe fn make_current(window: &'a WindowWrapper, context: &'b ContextWrapper) - -> Result, CreationError> - { - let previous_hdc = gl::wgl::GetCurrentDC() as winapi::HDC; - let previous_hglrc = gl::wgl::GetCurrentContext() as winapi::HGLRC; - - let result = gl::wgl::MakeCurrent(window.1 as *const libc::c_void, - context.0 as *const libc::c_void); - - if result == 0 { - return Err(CreationError::OsError(format!("wglMakeCurrent function failed: {}", - format!("{}", io::Error::last_os_error())))); - } - - Ok(CurrentContextGuard { - previous_hdc: previous_hdc, - previous_hglrc: previous_hglrc, - marker1: PhantomData, - marker2: PhantomData, - }) - } -} - -impl<'a, 'b> Drop for CurrentContextGuard<'a, 'b> { - fn drop(&mut self) { - unsafe { - gl::wgl::MakeCurrent(self.previous_hdc as *const libc::c_void, - self.previous_hglrc as *const libc::c_void); - } - } -} diff --git a/src/win32/mod.rs b/src/win32/mod.rs deleted file mode 100644 index 4a9dcbf..0000000 --- a/src/win32/mod.rs +++ /dev/null @@ -1,417 +0,0 @@ -use std::sync::atomic::AtomicBool; -use std::mem; -use std::ptr; -use std::ffi::CString; -use std::ffi::OsStr; -use std::os::windows::ffi::OsStrExt; -use std::sync::{ - Arc, - Mutex -}; -use std::sync::mpsc::Receiver; -use libc; -use {CreationError, Event, MouseCursor}; -use CursorState; - -use PixelFormat; -use BuilderAttribs; - -pub use self::headless::HeadlessContext; -pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor}; - -use winapi; -use user32; -use kernel32; -use gdi32; - -mod callback; -mod event; -mod gl; -mod headless; -mod init; -mod make_current_guard; -mod monitor; - -/// The Win32 implementation of the main `Window` object. -pub struct Window { - /// Main handle for the window. - window: WindowWrapper, - - /// OpenGL context. - context: ContextWrapper, - - /// Binded to `opengl32.dll`. - /// - /// `wglGetProcAddress` returns null for GL 1.1 functions because they are - /// already defined by the system. This module contains them. - gl_library: winapi::HMODULE, - - /// Receiver for the events dispatched by the window callback. - events_receiver: Receiver, - - /// True if a `Closed` event has been received. - is_closed: AtomicBool, - - /// The current cursor state. - cursor_state: Arc>, - - /// The pixel format that has been used to create this window. - pixel_format: PixelFormat, -} - -unsafe impl Send for Window {} -unsafe impl Sync for Window {} - -/// A simple wrapper that destroys the context when it is destroyed. -// FIXME: remove `pub` (https://github.com/rust-lang/rust/issues/23585) -#[doc(hidden)] -pub struct ContextWrapper(pub winapi::HGLRC); - -impl Drop for ContextWrapper { - fn drop(&mut self) { - unsafe { - gl::wgl::DeleteContext(self.0 as *const libc::c_void); - } - } -} - -/// A simple wrapper that destroys the window when it is destroyed. -// FIXME: remove `pub` (https://github.com/rust-lang/rust/issues/23585) -#[doc(hidden)] -pub struct WindowWrapper(pub winapi::HWND, pub winapi::HDC); - -impl Drop for WindowWrapper { - fn drop(&mut self) { - unsafe { - user32::DestroyWindow(self.0); - } - } -} - -#[derive(Clone)] -pub struct WindowProxy; - -impl WindowProxy { - pub fn wakeup_event_loop(&self) { - unimplemented!() - } -} - -impl Window { - /// See the docs in the crate root file. - pub fn new(builder: BuilderAttribs) -> Result { - let (builder, sharing) = builder.extract_non_static(); - let sharing = sharing.map(|w| init::ContextHack(w.context.0)); - init::new_window(builder, sharing) - } - - /// See the docs in the crate root file. - pub fn is_closed(&self) -> bool { - 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) { - let text = OsStr::new(text).encode_wide().chain(Some(0).into_iter()) - .collect::>(); - - unsafe { - user32::SetWindowTextW(self.window.0, text.as_ptr() as winapi::LPCWSTR); - } - } - - pub fn show(&self) { - unsafe { - user32::ShowWindow(self.window.0, winapi::SW_SHOW); - } - } - - pub fn hide(&self) { - unsafe { - user32::ShowWindow(self.window.0, winapi::SW_HIDE); - } - } - - /// See the docs in the crate root file. - pub fn get_position(&self) -> Option<(i32, i32)> { - use std::mem; - - let mut placement: winapi::WINDOWPLACEMENT = unsafe { mem::zeroed() }; - placement.length = mem::size_of::() as winapi::UINT; - - if unsafe { user32::GetWindowPlacement(self.window.0, &mut placement) } == 0 { - return None - } - - let ref rect = placement.rcNormalPosition; - Some((rect.left as i32, rect.top as i32)) - } - - /// See the docs in the crate root file. - pub fn set_position(&self, x: i32, y: i32) { - use libc; - - unsafe { - user32::SetWindowPos(self.window.0, ptr::null_mut(), x as libc::c_int, y as libc::c_int, - 0, 0, winapi::SWP_NOZORDER | winapi::SWP_NOSIZE); - user32::UpdateWindow(self.window.0); - } - } - - /// See the docs in the crate root file. - pub fn get_inner_size(&self) -> Option<(u32, u32)> { - let mut rect: winapi::RECT = unsafe { mem::uninitialized() }; - - if unsafe { user32::GetClientRect(self.window.0, &mut rect) } == 0 { - return None - } - - Some(( - (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<(u32, u32)> { - let mut rect: winapi::RECT = unsafe { mem::uninitialized() }; - - if unsafe { user32::GetWindowRect(self.window.0, &mut rect) } == 0 { - return None - } - - Some(( - (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: u32, y: u32) { - use libc; - - unsafe { - user32::SetWindowPos(self.window.0, ptr::null_mut(), 0, 0, x as libc::c_int, - y as libc::c_int, winapi::SWP_NOZORDER | winapi::SWP_NOREPOSITION); - user32::UpdateWindow(self.window.0); - } - } - - pub fn create_window_proxy(&self) -> WindowProxy { - WindowProxy - } - - /// See the docs in the crate root file. - pub fn poll_events(&self) -> PollEventsIterator { - PollEventsIterator { - window: self, - } - } - - /// See the docs in the crate root file. - pub fn wait_events(&self) -> WaitEventsIterator { - WaitEventsIterator { - window: self, - } - } - - /// See the docs in the crate root file. - pub unsafe fn make_current(&self) { - // TODO: check return value - gl::wgl::MakeCurrent(self.window.1 as *const libc::c_void, - self.context.0 as *const libc::c_void); - } - - /// See the docs in the crate root file. - pub fn is_current(&self) -> bool { - unsafe { gl::wgl::GetCurrentContext() == self.context.0 as *const libc::c_void } - } - - /// See the docs in the crate root file. - pub fn get_proc_address(&self, addr: &str) -> *const () { - let addr = CString::new(addr.as_bytes()).unwrap(); - let addr = addr.as_ptr(); - - unsafe { - let p = gl::wgl::GetProcAddress(addr) as *const (); - if !p.is_null() { return p; } - kernel32::GetProcAddress(self.gl_library, addr) as *const () - } - } - - /// See the docs in the crate root file. - pub fn swap_buffers(&self) { - unsafe { - gdi32::SwapBuffers(self.window.1); - } - } - - pub fn platform_display(&self) -> *mut libc::c_void { - unimplemented!() - } - - pub fn platform_window(&self) -> *mut libc::c_void { - self.window.0 as *mut libc::c_void - } - - /// See the docs in the crate root file. - pub fn get_api(&self) -> ::Api { - ::Api::OpenGl - } - - pub fn get_pixel_format(&self) -> PixelFormat { - self.pixel_format.clone() - } - - pub fn set_window_resize_callback(&mut self, _: Option) { - } - - pub fn set_cursor(&self, _cursor: MouseCursor) { - unimplemented!() - } - - pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> { - let mut current_state = self.cursor_state.lock().unwrap(); - - let foreground_thread_id = unsafe { user32::GetWindowThreadProcessId(self.window.0, ptr::null_mut()) }; - let current_thread_id = unsafe { kernel32::GetCurrentThreadId() }; - - unsafe { user32::AttachThreadInput(foreground_thread_id, current_thread_id, 1) }; - - let res = match (state, *current_state) { - (CursorState::Normal, CursorState::Normal) => Ok(()), - (CursorState::Hide, CursorState::Hide) => Ok(()), - (CursorState::Grab, CursorState::Grab) => Ok(()), - - (CursorState::Hide, CursorState::Normal) => { - unsafe { - user32::SetCursor(ptr::null_mut()); - *current_state = CursorState::Hide; - Ok(()) - } - }, - - (CursorState::Normal, CursorState::Hide) => { - unsafe { - user32::SetCursor(user32::LoadCursorW(ptr::null_mut(), winapi::IDC_ARROW)); - *current_state = CursorState::Normal; - Ok(()) - } - }, - - (CursorState::Grab, CursorState::Normal) => { - unsafe { - user32::SetCursor(ptr::null_mut()); - let mut rect = mem::uninitialized(); - if user32::GetClientRect(self.window.0, &mut rect) == 0 { - return Err(format!("GetWindowRect failed")); - } - user32::ClientToScreen(self.window.0, mem::transmute(&mut rect.left)); - user32::ClientToScreen(self.window.0, mem::transmute(&mut rect.right)); - if user32::ClipCursor(&rect) == 0 { - return Err(format!("ClipCursor failed")); - } - *current_state = CursorState::Grab; - Ok(()) - } - }, - - (CursorState::Normal, CursorState::Grab) => { - unsafe { - user32::SetCursor(user32::LoadCursorW(ptr::null_mut(), winapi::IDC_ARROW)); - if user32::ClipCursor(ptr::null()) == 0 { - return Err(format!("ClipCursor failed")); - } - *current_state = CursorState::Normal; - Ok(()) - } - }, - - _ => unimplemented!(), - }; - - unsafe { user32::AttachThreadInput(foreground_thread_id, current_thread_id, 0) }; - - res - } - - pub fn hidpi_factor(&self) -> f32 { - 1.0 - } - - pub fn set_cursor_position(&self, x: i32, y: i32) -> Result<(), ()> { - let mut point = winapi::POINT { - x: x, - y: y, - }; - - unsafe { - if user32::ClientToScreen(self.window.0, &mut point) == 0 { - return Err(()); - } - - if user32::SetCursorPos(point.x, point.y) == 0 { - return Err(()); - } - } - - Ok(()) - } -} - -pub struct PollEventsIterator<'a> { - window: &'a Window, -} - -impl<'a> Iterator for PollEventsIterator<'a> { - type Item = Event; - - fn next(&mut self) -> Option { - use events::Event::Closed; - - match self.window.events_receiver.try_recv() { - Ok(Closed) => { - use std::sync::atomic::Ordering::Relaxed; - self.window.is_closed.store(true, Relaxed); - Some(Closed) - }, - Ok(ev) => Some(ev), - Err(_) => None - } - } -} - -pub struct WaitEventsIterator<'a> { - window: &'a Window, -} - -impl<'a> Iterator for WaitEventsIterator<'a> { - type Item = Event; - - fn next(&mut self) -> Option { - use events::Event::Closed; - - match self.window.events_receiver.recv() { - Ok(Closed) => { - use std::sync::atomic::Ordering::Relaxed; - self.window.is_closed.store(true, Relaxed); - Some(Closed) - }, - Ok(ev) => Some(ev), - Err(_) => None - } - } -} - -impl Drop for Window { - fn drop(&mut self) { - unsafe { - // we don't call MakeCurrent(0, 0) because we are not sure that the context - // is still the current one - user32::PostMessageW(self.window.0, winapi::WM_DESTROY, 0, 0); - } - } -} diff --git a/src/win32/monitor.rs b/src/win32/monitor.rs deleted file mode 100644 index 4b592cb..0000000 --- a/src/win32/monitor.rs +++ /dev/null @@ -1,180 +0,0 @@ -use winapi; -use user32; - -use std::collections::VecDeque; -use std::mem; - -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. - monitor_name: String, - - /// Name to give to the user. - readable_name: String, - - /// See the `StateFlags` element here: - /// http://msdn.microsoft.com/en-us/library/dd183569(v=vs.85).aspx - flags: winapi::DWORD, - - /// True if this is the primary monitor. - primary: bool, - - /// The position of the monitor in pixels on the desktop. - /// - /// A window that is positionned at these coordinates will overlap the monitor. - position: (u32, u32), - - /// The current resolution in pixels on the monitor. - dimensions: (u32, u32), -} - -struct DeviceEnumerator { - parent_device: *const winapi::WCHAR, - current_index: u32, -} - -impl DeviceEnumerator { - fn adapters() -> DeviceEnumerator { - use std::ptr; - DeviceEnumerator { - parent_device: ptr::null(), - current_index: 0 - } - } - - 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 { - use std::mem; - loop { - let mut output: winapi::DISPLAY_DEVICEW = unsafe { mem::zeroed() }; - output.cb = mem::size_of::() as winapi::DWORD; - - 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 - { - // the device is not active - // the Win32 api usually returns a lot of inactive devices - continue; - } - - return Some(output); - } - None - } -} - -fn wchar_as_string(wchar: &[winapi::WCHAR]) -> String { - String::from_utf16_lossy(wchar) - .trim_right_matches(0 as char) - .to_string() -} - -/// Win32 implementation of the main `get_available_monitors` function. -pub fn get_available_monitors() -> VecDeque { - // 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::() as winapi::WORD; - - if user32::EnumDisplaySettingsExW(adapter.DeviceName.as_ptr(), - winapi::ENUM_CURRENT_SETTINGS, - &mut dev, 0) == 0 - { - continue; - } - - let point: &winapi::POINTL = mem::transmute(&dev.union1); - let position = (point.x as u32, point.y as u32); - - let dimensions = (dev.dmPelsWidth as u32, dev.dmPelsHeight as u32); - - (position, dimensions) - }; - - for (num, monitor) in DeviceEnumerator::monitors(adapter.DeviceName.as_ptr()).enumerate() { - // adding to the resulting list - result.push_back(MonitorID { - adapter_name: adapter.DeviceName, - monitor_name: wchar_as_string(&monitor.DeviceName), - readable_name: wchar_as_string(&monitor.DeviceString), - flags: monitor.StateFlags, - primary: (adapter.StateFlags & winapi::DISPLAY_DEVICE_PRIMARY_DEVICE) != 0 && - num == 0, - position: position, - dimensions: dimensions, - }); - } - } - result -} - -/// Win32 implementation of the main `get_primary_monitor` function. -pub fn get_primary_monitor() -> MonitorID { - // we simply get all available monitors and return the one with the `PRIMARY_DEVICE` flag - // TODO: it is possible to query the win32 API for the primary monitor, this should be done - // instead - for monitor in get_available_monitors().into_iter() { - if monitor.primary { - return monitor; - } - } - - panic!("Failed to find the primary monitor") -} - -impl MonitorID { - /// See the docs if the crate root file. - pub fn get_name(&self) -> Option { - Some(self.readable_name.clone()) - } - - /// See the docs of the crate root file. - pub fn get_native_identifier(&self) -> NativeMonitorId { - NativeMonitorId::Name(self.monitor_name.clone()) - } - - /// See the docs if the crate root file. - pub fn get_dimensions(&self) -> (u32, u32) { - // TODO: retreive the dimensions every time this is called - self.dimensions - } - - /// 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 - } - - /// This is a Win32-only function for `MonitorID` that returns the position of the - /// monitor on the desktop. - /// A window that is positionned at these coordinates will overlap the monitor. - pub fn get_position(&self) -> (u32, u32) { - self.position - } -} -- cgit v1.2.3