From 0b2911ca302020a6e365eec60fa0494f56ef70e1 Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Tue, 8 Dec 2015 22:57:14 +0100 Subject: [PATCH] New version running with keyboard support --- examples/noise.rs | 12 ++- src/lib.rs | 82 ++++++++-------- src/windows.rs | 233 +++++++++++++++++++++++++--------------------- 3 files changed, 177 insertions(+), 150 deletions(-) diff --git a/examples/noise.rs b/examples/noise.rs index 28a3155..523a02a 100644 --- a/examples/noise.rs +++ b/examples/noise.rs @@ -12,9 +12,9 @@ fn main() { let mut buffer: [u32; WIDTH * HEIGHT] = [0; WIDTH * HEIGHT]; - let mut mfb = Minifb::new("Noise Test - Press ESC to exit", WIDTH, HEIGHT).unwrap(); + let mut window = Window::new("Noise Test - Press ESC to exit", WIDTH, HEIGHT, Scale::X1, Vsync::No).unwrap(); - while mfb.update(&buffer) { + while window.update(&buffer) { for i in buffer.iter_mut() { noise = seed; noise >>= 3; @@ -26,5 +26,13 @@ fn main() { noise &= 0xFF; *i = (noise << 16) | (noise << 8) | noise; } + + for key in window.get_keys().iter() { + match *key { + Key::A => println!("Pressed A"), + Key::B => println!("Pressed B"), + _ => (), + } + } } } diff --git a/src/lib.rs b/src/lib.rs index 1d322d4..cab0b79 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,6 @@ extern crate cgl; extern crate cocoa; #[cfg(target_os = "macos")] extern crate core_foundation; -#[cfg(target_os = "macos")] /// Scale will scale the frame buffer and the window that is being sent in when calling the update /// function. This is useful if you for example want to display a 320 x 256 window on a screen with @@ -46,45 +45,44 @@ pub enum Vsync { BestGuess, } -/// pub enum Key { - Key1, - Key2, - Key3, - Key4, - Key5, - Key6, - Key7, - Key8, - Key9, - Key0, + Key0 = 0, + Key1 = 1, + Key2 = 2, + Key3 = 3, + Key4 = 4, + Key5 = 5, + Key6 = 6, + Key7 = 7, + Key8 = 8, + Key9 = 9, - A, - B, - C, - D, - E, - F, - G, - H, - I, - J, - K, - L, - M, - N, - O, - P, - Q, - R, - S, - T, - U, - V, - W, - X, - Y, - Z, + A = 10, + B = 11, + C = 12, + D = 13, + E = 14, + F = 15, + G = 16, + H = 17, + I = 18, + J = 19, + K = 20, + L = 21, + M = 22, + N = 23, + O = 24, + P = 25, + Q = 26, + R = 27, + S = 28, + T = 29, + U = 30, + V = 31, + W = 32, + X = 33, + Y = 34, + Z = 35, F1, F2, @@ -145,8 +143,8 @@ pub mod windows; #[cfg(target_os = "windows")] pub use windows::*; -#[cfg(target_os = "macos")] -pub mod macos; -#[cfg(target_os = "macos")] -pub use macos::*; +//#[cfg(target_os = "macos")] +//pub mod macos; +//#[cfg(target_os = "macos")] +//pub use macos::*; diff --git a/src/windows.rs b/src/windows.rs index 10c8cd6..6df07a2 100644 --- a/src/windows.rs +++ b/src/windows.rs @@ -9,6 +9,8 @@ use Scale; use Vsync; use Key; +//use Keys; + use std::ffi::CString; use std::ptr; use std::os::windows::ffi::OsStrExt; @@ -16,6 +18,7 @@ use std::ffi::OsStr; use std::mem; use self::winapi::windef::HWND; +use self::winapi::windef::HDC; use self::winapi::winuser::WS_OVERLAPPEDWINDOW; use self::winapi::winuser::WNDCLASSW; use self::winapi::wingdi::BITMAPINFOHEADER; @@ -30,86 +33,85 @@ struct BitmapInfo { pub bmi_colors: [RGBQUAD; 3], } -fn update_key_state(window: &mut Window, wparam: u32, bool state) { +fn update_key_state(window: &mut Window, wparam: u32, state: bool) { match wparam & 0x1ff { - 0x00B => window.keys[Key::Key0] = state, - 0x002 => window.keys[Key::Key1] = state, - 0x003 => window.keys[Key::Key2] = state, - 0x004 => window.keys[Key::Key3] = state, - 0x005 => window.keys[Key::Key4] = state, - 0x006 => window.keys[Key::Key5] = state, - 0x007 => window.keys[Key::Key6] = state, - 0x008 => window.keys[Key::Key7] = state, - 0x009 => window.keys[Key::Key8] = state, - 0x00A => window.keys[Key::Key9] = state, - 0x01E => window.keys[Key::A] = state, - 0x030 => window.keys[Key::B] = state, - 0x02E => window.keys[Key::C] = state, - 0x020 => window.keys[Key::D] = state, - 0x012 => window.keys[Key::E] = state, - 0x021 => window.keys[Key::F] = state, - 0x022 => window.keys[Key::G] = state, - 0x023 => window.keys[Key::H] = state, - 0x017 => window.keys[Key::I] = state, - 0x024 => window.keys[Key::J] = state, - 0x025 => window.keys[Key::K] = state, - 0x026 => window.keys[Key::L] = state, - 0x032 => window.keys[Key::M] = state, - 0x031 => window.keys[Key::N] = state, - 0x018 => window.keys[Key::O] = state, - 0x019 => window.keys[Key::P] = state, - 0x010 => window.keys[Key::Q] = state, - 0x013 => window.keys[Key::R] = state, - 0x01F => window.keys[Key::S] = state, - 0x014 => window.keys[Key::T] = state, - 0x016 => window.keys[Key::U] = state, - 0x02F => window.keys[Key::V] = state, - 0x011 => window.keys[Key::W] = state, - 0x02D => window.keys[Key::X] = state, - 0x015 => window.keys[Key::Y] = state, - 0x02C => window.keys[Key::Z] = state, - 0x03B => window.keys[Key::F1] = state, - 0x03C => window.keys[Key::F2] = state, - 0x03D => window.keys[Key::F3] = state, - 0x03E => window.keys[Key::F4] = state, - 0x03F => window.keys[Key::F5] = state, - 0x040 => window.keys[Key::F6] = state, - 0x041 => window.keys[Key::F7] = state, - 0x042 => window.keys[Key::F8] = state, - 0x043 => window.keys[Key::F9] = state, - 0x042 => window.keys[Key::F8] = state, - 0x043 => window.keys[Key::F9] = state, - 0x044 => window.keys[Key::F10] = state, - 0x057 => window.keys[Key::F11] = state, - 0x058 => window.keys[Key::F12] = state, - 0x150 => window.keys[Key::Down] = state, - 0x14B => window.keys[Key::Left] = state, - 0x14D => window.keys[Key::Right] = state, - 0x148 => window.keys[Key::Up] = state, - 0x028 => window.keys[Key::Apostrophe] = state, - 0x02B => window.keys[Key::Backslash] = state, - 0x033 => window.keys[Key::Comma] = state, - 0x00D => window.keys[Key::Equal] = state, - 0x01A => window.keys[Key::LeftBracket] = state, - 0x00C => window.keys[Key::Minus] = state, - 0x034 => window.keys[Key::Period] = state, - 0x01B => window.keys[Key::RightBracket] = state, - 0x027 => window.keys[Key::Semicolon] = state, - 0x035 => window.keys[Key::Slash] = state, - 0x00E => window.keys[Key::Backspace] = state, - 0x153 => window.keys[Key::Delete] = state, - 0x14F => window.keys[Key::End] = state, - 0x01C => window.keys[Key::Enter] = state, - 0x001 => window.keys[Key::Escape] = state, - 0x147 => window.keys[Key::Home] = state, - 0x152 => window.keys[Key::Insert] = state, - 0x15D => window.keys[Key::Menu] = state, - 0x151 => window.keys[Key::PageDown] = state, - 0x149 => window.keys[Key::PageUp] = state, - 0x045 => window.keys[Key::Pause] = state, - 0x039 => window.keys[Key::Space] = state, - 0x00F => window.keys[Key::Tab] = state, - 0x03A => window.keys[Key::CapsLock] = state, + 0x00B => window.keys[Key::Key0 as usize] = state, + 0x002 => window.keys[Key::Key1 as usize] = state, + 0x003 => window.keys[Key::Key2 as usize] = state, + 0x004 => window.keys[Key::Key3 as usize] = state, + 0x005 => window.keys[Key::Key4 as usize] = state, + 0x006 => window.keys[Key::Key5 as usize] = state, + 0x007 => window.keys[Key::Key6 as usize] = state, + 0x008 => window.keys[Key::Key7 as usize] = state, + 0x009 => window.keys[Key::Key8 as usize] = state, + 0x00A => window.keys[Key::Key9 as usize] = state, + 0x01E => window.keys[Key::A as usize] = state, + 0x030 => window.keys[Key::B as usize] = state, + 0x02E => window.keys[Key::C as usize] = state, + 0x020 => window.keys[Key::D as usize] = state, + 0x012 => window.keys[Key::E as usize] = state, + 0x021 => window.keys[Key::F as usize] = state, + 0x022 => window.keys[Key::G as usize] = state, + 0x023 => window.keys[Key::H as usize] = state, + 0x017 => window.keys[Key::I as usize] = state, + 0x024 => window.keys[Key::J as usize] = state, + 0x025 => window.keys[Key::K as usize] = state, + 0x026 => window.keys[Key::L as usize] = state, + 0x032 => window.keys[Key::M as usize] = state, + 0x031 => window.keys[Key::N as usize] = state, + 0x018 => window.keys[Key::O as usize] = state, + 0x019 => window.keys[Key::P as usize] = state, + 0x010 => window.keys[Key::Q as usize] = state, + 0x013 => window.keys[Key::R as usize] = state, + 0x01F => window.keys[Key::S as usize] = state, + 0x014 => window.keys[Key::T as usize] = state, + 0x016 => window.keys[Key::U as usize] = state, + 0x02F => window.keys[Key::V as usize] = state, + 0x011 => window.keys[Key::W as usize] = state, + 0x02D => window.keys[Key::X as usize] = state, + 0x015 => window.keys[Key::Y as usize] = state, + 0x02C => window.keys[Key::Z as usize] = state, + 0x03B => window.keys[Key::F1 as usize] = state, + 0x03C => window.keys[Key::F2 as usize] = state, + 0x03D => window.keys[Key::F3 as usize] = state, + 0x03E => window.keys[Key::F4 as usize] = state, + 0x03F => window.keys[Key::F5 as usize] = state, + 0x040 => window.keys[Key::F6 as usize] = state, + 0x041 => window.keys[Key::F7 as usize] = state, + 0x042 => window.keys[Key::F8 as usize] = state, + 0x043 => window.keys[Key::F9 as usize] = state, + 0x044 => window.keys[Key::F10 as usize] = state, + 0x057 => window.keys[Key::F11 as usize] = state, + 0x058 => window.keys[Key::F12 as usize] = state, + 0x150 => window.keys[Key::Down as usize] = state, + 0x14B => window.keys[Key::Left as usize] = state, + 0x14D => window.keys[Key::Right as usize] = state, + 0x148 => window.keys[Key::Up as usize] = state, + 0x028 => window.keys[Key::Apostrophe as usize] = state, + 0x02B => window.keys[Key::Backslash as usize] = state, + 0x033 => window.keys[Key::Comma as usize] = state, + 0x00D => window.keys[Key::Equal as usize] = state, + 0x01A => window.keys[Key::LeftBracket as usize] = state, + 0x00C => window.keys[Key::Minus as usize] = state, + 0x034 => window.keys[Key::Period as usize] = state, + 0x01B => window.keys[Key::RightBracket as usize] = state, + 0x027 => window.keys[Key::Semicolon as usize] = state, + 0x035 => window.keys[Key::Slash as usize] = state, + 0x00E => window.keys[Key::Backspace as usize] = state, + 0x153 => window.keys[Key::Delete as usize] = state, + 0x14F => window.keys[Key::End as usize] = state, + 0x01C => window.keys[Key::Enter as usize] = state, + 0x001 => window.keys[Key::Escape as usize] = state, + 0x147 => window.keys[Key::Home as usize] = state, + 0x152 => window.keys[Key::Insert as usize] = state, + 0x15D => window.keys[Key::Menu as usize] = state, + 0x151 => window.keys[Key::PageDown as usize] = state, + 0x149 => window.keys[Key::PageUp as usize] = state, + 0x045 => window.keys[Key::Pause as usize] = state, + 0x039 => window.keys[Key::Space as usize] = state, + 0x00F => window.keys[Key::Tab as usize] = state, + 0x03A => window.keys[Key::CapsLock as usize] = state, + _ => (), } } @@ -124,21 +126,22 @@ unsafe extern "system" fn wnd_proc(window: winapi::HWND, let user_data = user32::GetWindowLongPtrW(window, winapi::winuser::GWLP_USERDATA); - if user_data == 0 + if user_data == 0 { return user32::DefWindowProcW(window, msg, wparam, lparam); + } - let mut self = user_data as &mut Window; + let mut wnd: &mut Window = mem::transmute(user_data); match msg { winapi::winuser::WM_KEYDOWN => { - update_key_state(self, wparam as u32, true); + update_key_state(wnd, (lparam as u32) >> 16, true); if (wparam & 0x1ff) == 27 { CLOSE_APP = true; } } winapi::winuser::WM_KEYUP => { - update_key_state(self, wparam as u32, false); + update_key_state(wnd, (lparam as u32) >> 16, false); } winapi::winuser::WM_PAINT => { @@ -160,7 +163,7 @@ unsafe extern "system" fn wnd_proc(window: winapi::HWND, bitmap_info.bmi_colors[1].rgbGreen = 0xff; bitmap_info.bmi_colors[2].rgbBlue = 0xff; - gdi32::StretchDIBits(self.dc, + gdi32::StretchDIBits(wnd.dc.unwrap(), 0, 0, width, @@ -169,7 +172,7 @@ unsafe extern "system" fn wnd_proc(window: winapi::HWND, 0, width, height, - mem::transmute(self.buffer), + mem::transmute(wnd.buffer.as_ptr()), mem::transmute(&bitmap_info), winapi::wingdi::DIB_RGB_COLORS, winapi::wingdi::SRCCOPY); @@ -193,14 +196,14 @@ fn to_wstring(str: &str) -> *const u16 { } pub struct Window { - dc: DC, - window: HWND, - bool keys_down: [bool; 512], - buffer: &[u32], + dc: Option, + window: Option, + keys: [bool; 512], + buffer: Vec, } impl Window { - fn open_window(name: &str, width: usize, height: usize, _: Scale, _: Vsync) -> Result { + fn open_window(name: &str, width: usize, height: usize, _: Scale, _: Vsync) -> HWND { unsafe { let class_name = to_wstring("minifb_window"); let s = CString::new(name).unwrap(); @@ -253,26 +256,39 @@ impl Window { user32::ShowWindow(handle, winapi::SW_NORMAL); } + return handle; } } - pub fn new(name: &str, width: usize, height: usize) -> Option { - let handle = Minifb::open_window(name, width, height); + pub fn new(name: &str, width: usize, height: usize, scale: Scale, vsync: Vsync) -> Result { + unsafe { + let handle = Self::open_window(name, width, height, scale, vsync); - match handle.is_null() { - true => None, - false => Some(Minifb { window: handle }), + if handle.is_null() { + return Err("Unable to create Window"); + } + + let window = Window { + dc: Some(user32::GetDC(handle)), + window: Some(handle), + keys: [false; 512], + buffer: Vec::new(), + }; + + Ok(window) } } - pub fn get_keys(&self -> Vec { - let index = 0; + pub fn get_keys(&self) -> Vec { + let mut index: u8 = 0; let mut keys: Vec = Vec::new(); - for i in self.keys { + for i in self.keys.iter() { if *i { - keys.push(index as Key); + unsafe { + keys.push(mem::transmute(index)); + } } index += 1; @@ -284,11 +300,16 @@ impl Window { pub fn update(&mut self, buffer: &[u32]) -> bool { unsafe { let mut msg = mem::uninitialized(); + let window = self.window.unwrap(); - user32::SetWindowLongPtrW(self.window, winapi::winuser::GWLP_USERDATA, self as i64); - user32::InvalidateRect(self.window, ptr::null_mut(), winapi::TRUE); + // TODO: Optimize - while user32::PeekMessageW(&mut msg, self.window, 0, 0, winapi::winuser::PM_REMOVE) != 0 { + self.buffer = buffer.iter().cloned().collect(); + + user32::SetWindowLongPtrW(window, winapi::winuser::GWLP_USERDATA, mem::transmute(self)); + user32::InvalidateRect(window, ptr::null_mut(), winapi::TRUE); + + while user32::PeekMessageW(&mut msg, window, 0, 0, winapi::winuser::PM_REMOVE) != 0 { user32::TranslateMessage(&mut msg); user32::DispatchMessageW(&mut msg); } @@ -303,12 +324,12 @@ impl Window { impl Drop for Window { fn drop(&mut self) { unsafe { - if self.dc.is_valid() { - user32::ReleaseDC(self.window, self.dc); + if self.dc.is_some() { + user32::ReleaseDC(self.window.unwrap(), self.dc.unwrap()); } - if self.hwnd.is_valid() { - user32::CloseWindow(self.hwnd); + if self.window.is_some() { + user32::CloseWindow(self.window.unwrap()); } } }