Merge pull request #277 from tomaka/win32-callback

Extract callback from win32/init.rs to its own module
This commit is contained in:
tomaka 2015-02-16 11:03:21 +01:00
commit 19debf3eb2
3 changed files with 200 additions and 233 deletions

194
src/win32/callback.rs Normal file
View file

@ -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)
}
}
}

View file

@ -1,15 +1,13 @@
use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicBool;
use std::ptr; use std::ptr;
use super::event; use super::callback;
use super::Window; use super::Window;
use BuilderAttribs; use BuilderAttribs;
use {CreationError, Event}; use CreationError;
use CreationError::OsError; use CreationError::OsError;
use std::cell::RefCell;
use std::ffi::CString; use std::ffi::CString;
use std::rc::Rc; use std::sync::mpsc::channel;
use std::sync::mpsc::{Sender, Receiver, channel};
use libc; use libc;
use super::gl; use super::gl;
@ -18,12 +16,6 @@ use kernel32;
use user32; use user32;
use gdi32; 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 /// Work-around the fact that HGLRC doesn't implement Send
pub struct ContextHack(pub winapi::HGLRC); pub struct ContextHack(pub winapi::HGLRC);
unsafe impl Send for ContextHack {} unsafe impl Send for ContextHack {}
@ -54,7 +46,7 @@ pub fn new_window(builder: BuilderAttribs<'static>, builder_sharelists: Option<C
let class = winapi::WNDCLASSEXW { let class = winapi::WNDCLASSEXW {
cbSize: mem::size_of::<winapi::WNDCLASSEXW>() as winapi::UINT, cbSize: mem::size_of::<winapi::WNDCLASSEXW>() as winapi::UINT,
style: winapi::CS_HREDRAW | winapi::CS_VREDRAW | winapi::CS_OWNDC, style: winapi::CS_HREDRAW | winapi::CS_VREDRAW | winapi::CS_OWNDC,
lpfnWndProc: callback, lpfnWndProc: callback::callback,
cbClsExtra: 0, cbClsExtra: 0,
cbWndExtra: 0, cbWndExtra: 0,
hInstance: unsafe { kernel32::GetModuleHandleW(ptr::null()) }, 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 events_receiver = {
let (tx, rx) = channel(); let (tx, rx) = channel();
let mut tx = Some(tx); let mut tx = Some(tx);
WINDOW.with(|window| { callback::WINDOW.with(|window| {
(*window.borrow_mut()) = Some((real_window, tx.take().unwrap())); (*window.borrow_mut()) = Some((real_window, tx.take().unwrap()));
}); });
rx rx
@ -423,223 +415,3 @@ pub fn new_window(builder: BuilderAttribs<'static>, builder_sharelists: Option<C
rx.recv().unwrap() 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,
}
}*/

View file

@ -16,6 +16,7 @@ use user32;
use kernel32; use kernel32;
use gdi32; use gdi32;
mod callback;
mod event; mod event;
mod gl; mod gl;
mod headless; mod headless;