diff options
-rw-r--r-- | src/win32/callback.rs | 194 | ||||
-rw-r--r-- | src/win32/init.rs | 238 | ||||
-rw-r--r-- | src/win32/mod.rs | 1 |
3 files changed, 200 insertions, 233 deletions
diff --git a/src/win32/callback.rs b/src/win32/callback.rs new file mode 100644 index 0000000..5423fc3 --- /dev/null +++ b/src/win32/callback.rs @@ -0,0 +1,194 @@ +use std::rc::Rc; +use std::cell::RefCell; +use std::sync::mpsc::{Sender, Receiver, channel}; + +use Event; +use super::event; + +use user32; +use winapi; + +/// Stores the current window and its events dispatcher. +/// +/// We only have one window per thread. We still store the HWND in case where we +/// receive an event for another window. +thread_local!(pub static WINDOW: Rc<RefCell<Option<(winapi::HWND, Sender<Event>)>>> = Rc::new(RefCell::new(None))); + +/// 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) { + WINDOW.with(|window| { + let window = window.borrow(); + let stored = match *window { + None => return, + Some(ref v) => v + }; + + let &(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 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; + + WINDOW.with(|w| { + let w = w.borrow(); + let &(ref win, _) = match *w { + None => return, + Some(ref v) => v + }; + + if win == &window { + unsafe { 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 = unsafe { 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_SETFOCUS => { + use events::Event::Focused; + send_event(window, Focused(true)); + 0 + }, + + winapi::WM_KILLFOCUS => { + use events::Event::Focused; + send_event(window, Focused(false)); + 0 + }, + + _ => unsafe { + user32::DefWindowProcW(window, msg, wparam, lparam) + } + } +} diff --git a/src/win32/init.rs b/src/win32/init.rs index 9e0e3a7..c3352b6 100644 --- a/src/win32/init.rs +++ b/src/win32/init.rs @@ -1,15 +1,13 @@ use std::sync::atomic::AtomicBool; use std::ptr; -use super::event; +use super::callback; use super::Window; use BuilderAttribs; -use {CreationError, Event}; +use CreationError; use CreationError::OsError; -use std::cell::RefCell; use std::ffi::CString; -use std::rc::Rc; -use std::sync::mpsc::{Sender, Receiver, channel}; +use std::sync::mpsc::channel; use libc; use super::gl; @@ -18,12 +16,6 @@ use kernel32; use user32; use gdi32; -/// Stores the current window and its events dispatcher. -/// -/// We only have one window per thread. We still store the HWND in case where we -/// receive an event for another window. -thread_local!(static WINDOW: Rc<RefCell<Option<(winapi::HWND, Sender<Event>)>>> = Rc::new(RefCell::new(None))); - /// Work-around the fact that HGLRC doesn't implement Send pub struct ContextHack(pub winapi::HGLRC); unsafe impl Send for ContextHack {} @@ -54,7 +46,7 @@ pub fn new_window(builder: BuilderAttribs<'static>, builder_sharelists: Option<C let class = winapi::WNDCLASSEXW { cbSize: mem::size_of::<winapi::WNDCLASSEXW>() as winapi::UINT, style: winapi::CS_HREDRAW | winapi::CS_VREDRAW | winapi::CS_OWNDC, - lpfnWndProc: callback, + lpfnWndProc: callback::callback, cbClsExtra: 0, cbWndExtra: 0, hInstance: unsafe { kernel32::GetModuleHandleW(ptr::null()) }, @@ -356,7 +348,7 @@ pub fn new_window(builder: BuilderAttribs<'static>, builder_sharelists: Option<C let events_receiver = { let (tx, rx) = channel(); let mut tx = Some(tx); - WINDOW.with(|window| { + callback::WINDOW.with(|window| { (*window.borrow_mut()) = Some((real_window, tx.take().unwrap())); }); rx @@ -423,223 +415,3 @@ pub fn new_window(builder: BuilderAttribs<'static>, builder_sharelists: Option<C rx.recv().unwrap() } - -/// 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) { - WINDOW.with(|window| { - let window = window.borrow(); - let stored = match *window { - None => return, - Some(ref v) => v - }; - - let &(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. -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; - - WINDOW.with(|w| { - let w = w.borrow(); - let &(ref win, _) = match *w { - None => return, - Some(ref v) => v - }; - - if win == &window { - unsafe { 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 = unsafe { 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_SETFOCUS => { - use events::Event::Focused; - send_event(window, Focused(true)); - 0 - }, - - winapi::WM_KILLFOCUS => { - use events::Event::Focused; - send_event(window, Focused(false)); - 0 - }, - - _ => unsafe { - user32::DefWindowProcW(window, msg, wparam, lparam) - } - } -} - -/*fn hints_to_pixelformat(hints: &Hints) -> winapi::PIXELFORMATDESCRIPTOR { - use std::mem; - - winapi::PIXELFORMATDESCRIPTOR { - nSize: size_of::<winapi::PIXELFORMATDESCRIPTOR>(), - nVersion: 1, - dwFlags: - if hints.stereo { PFD_STEREO } else { 0 }, - iPixelType: PFD_TYPE_RGBA, - cColorBits: hints.red_bits + hints.green_bits + hints.blue_bits, - cRedBits: - - pub nSize: WORD, - pub nVersion: WORD, - pub dwFlags: DWORD, - pub iPixelType: BYTE, - pub cColorBits: BYTE, - pub cRedBits: BYTE, - pub cRedShift: BYTE, - pub cGreenBits: BYTE, - pub cGreenShift: BYTE, - pub cBlueBits: BYTE, - pub cBlueShift: BYTE, - pub cAlphaBits: BYTE, - pub cAlphaShift: BYTE, - pub cAccumBits: BYTE, - pub cAccumRedBits: BYTE, - pub cAccumGreenBits: BYTE, - pub cAccumBlueBits: BYTE, - pub cAccumAlphaBits: BYTE, - pub cDepthBits: BYTE, - pub cStencilBits: BYTE, - pub cAuxBuffers: BYTE, - pub iLayerType: BYTE, - pub bReserved: BYTE, - pub dwLayerMask: DWORD, - pub dwVisibleMask: DWORD, - pub dwDamageMask: DWORD, - } -}*/ diff --git a/src/win32/mod.rs b/src/win32/mod.rs index c2fd103..7be42f8 100644 --- a/src/win32/mod.rs +++ b/src/win32/mod.rs @@ -15,6 +15,7 @@ use user32; use kernel32; use gdi32; +mod callback; mod event; mod gl; mod init; |