From c499697a9af7c33bb7ae9063988831e700d1f4de Mon Sep 17 00:00:00 2001 From: Mirko Covizzi Date: Mon, 15 Jun 2020 23:02:39 +0200 Subject: [PATCH] Windows: add basic event handling --- Cargo.toml | 2 +- src/win/event.rs | 23 ++++++++++++++++++ src/win/mod.rs | 7 ++++-- src/win/window.rs | 62 +++++++++++++++++++++++++++++++++-------------- 4 files changed, 73 insertions(+), 21 deletions(-) create mode 100644 src/win/event.rs diff --git a/Cargo.toml b/Cargo.toml index c1cd457..bdcf0bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ xcb = { version = "0.9", features = ["thread", "xlib_xcb", "dri2"] } x11 = { version = "2.3", features = ["xlib", "glx"]} [target.'cfg(target_os="windows")'.dependencies] -winapi = { version = "0.3.8", features = ["libloaderapi", "winuser", "windef", "minwindef", "guiddef", "combaseapi", "wingdi"] } +winapi = { version = "0.3.8", features = ["libloaderapi", "winuser", "windef", "minwindef", "guiddef", "combaseapi", "wingdi", "errhandlingapi"] } [target.'cfg(target_os="macos")'.dependencies] cocoa = "0.20.1" diff --git a/src/win/event.rs b/src/win/event.rs new file mode 100644 index 0000000..03d68cf --- /dev/null +++ b/src/win/event.rs @@ -0,0 +1,23 @@ +use std::sync::{Arc, Mutex}; + +use winapi::shared::minwindef::{LPARAM, LRESULT, UINT, WPARAM}; + +use crate::Window; +use winapi::um::winuser::WM_MOUSEMOVE; + +pub(crate) unsafe fn handle_message( + win: Arc>, + msg: UINT, + wparam: WPARAM, + lparam: LPARAM, +) -> LRESULT { + match msg { + WM_MOUSEMOVE => { + let x = (lparam & 0xFFFF) as i32; + let y = ((lparam >> 16) & 0xFFFF) as i32; + win.lock().unwrap().handle_mouse_motion(x, y); + 0 + } + _ => 0, + } +} diff --git a/src/win/mod.rs b/src/win/mod.rs index 1c54e26..d8b3e40 100644 --- a/src/win/mod.rs +++ b/src/win/mod.rs @@ -1,2 +1,5 @@ -mod window; -pub use window::*; +mod event; +mod window; + +pub use event::*; +pub use window::*; diff --git a/src/win/window.rs b/src/win/window.rs index 2700f35..912afda 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -15,14 +15,17 @@ use self::winapi::um::wingdi::{ }; use self::winapi::um::winuser::{ AdjustWindowRectEx, CreateWindowExA, DefWindowProcA, DestroyWindow, DispatchMessageA, GetDC, - MessageBoxA, PeekMessageA, PostQuitMessage, RegisterClassA, ReleaseDC, TranslateMessage, - UnregisterClassA, CS_OWNDC, MB_ICONERROR, MB_OK, MB_TOPMOST, MSG, - PM_REMOVE, WM_CLOSE, WM_QUIT, WNDCLASSA, WS_CAPTION, WS_CHILD, WS_CLIPSIBLINGS, WS_MAXIMIZEBOX, - WS_MINIMIZEBOX, WS_POPUPWINDOW, WS_SIZEBOX, WS_VISIBLE, + GetWindowLongPtrA, MessageBoxA, PeekMessageA, PostMessageA, RegisterClassA, ReleaseDC, + SetWindowLongPtrA, TranslateMessage, UnregisterClassA, CS_OWNDC, GWLP_USERDATA, MB_ICONERROR, + MB_OK, MB_TOPMOST, MSG, PM_REMOVE, WM_CREATE, WM_QUIT, WM_SHOWWINDOW, WNDCLASSA, WS_CAPTION, + WS_CHILD, WS_CLIPSIBLINGS, WS_MAXIMIZEBOX, WS_MINIMIZEBOX, WS_POPUPWINDOW, WS_SIZEBOX, + WS_VISIBLE, }; +use self::winapi::ctypes::c_void; use crate::Parent::WithParent; -use crate::WindowOpenOptions; +use crate::{handle_message, WindowOpenOptions}; +use std::sync::{Arc, Mutex}; unsafe fn message_box(title: &str, msg: &str) { let title = (title.to_owned() + "\0").as_ptr() as *const i8; @@ -68,16 +71,28 @@ fn handle_msg(_window: HWND) -> bool { unsafe extern "system" fn wnd_proc( hwnd: HWND, msg: UINT, - w_param: WPARAM, - l_param: LPARAM, + wparam: WPARAM, + lparam: LPARAM, ) -> LRESULT { + let win = GetWindowLongPtrA(hwnd, GWLP_USERDATA) as *const c_void; match msg { - WM_CLOSE => { - PostQuitMessage(0); + WM_CREATE => { + PostMessageA(hwnd, WM_SHOWWINDOW, 0, 0); + 0 + } + _ => { + if !win.is_null() { + let win: &Arc> = std::mem::transmute(win); + let win = Arc::clone(win); + let ret = handle_message(win, msg, wparam, lparam); + + // todo: need_reconfigure thing? + + // return ret + } + return DefWindowProcA(hwnd, msg, wparam, lparam); } - _ => return DefWindowProcA(hwnd, msg, w_param, l_param), } - 0 } unsafe fn register_wnd_class() -> ATOM { @@ -114,7 +129,7 @@ pub struct Window { } impl Window { - pub fn open(options: WindowOpenOptions) -> Self { + pub fn open(options: WindowOpenOptions) -> Arc> { unsafe { let mut window = Window { hwnd: null_mut(), @@ -188,26 +203,26 @@ impl Window { if pf_id == 0 { // todo: use a more useful return like an Option // todo: also launch error message boxes - return window; + return Arc::new(Mutex::new(window)); } if SetPixelFormat(window.hdc, pf_id, &pfd) == 0 { // todo: use a more useful return like an Option // todo: also launch error message boxes - return window; + return Arc::new(Mutex::new(window)); } window.gl_context = wglCreateContext(window.hdc); if window.gl_context == 0 as HGLRC { // todo: use a more useful return like an Option // todo: also launch error message boxes - return window; + return Arc::new(Mutex::new(window)); } if wglMakeCurrent(window.hdc, window.gl_context) == 0 { // todo: use a more useful return like an Option // todo: also launch error message boxes - return window; + return Arc::new(Mutex::new(window)); } let h = LoadLibraryA("opengl32.dll\0".as_ptr() as *const i8); @@ -217,6 +232,13 @@ impl Window { GetProcAddress(h, symbol) as *const _ }); + let hwnd = window.hwnd; + let hdc = window.hdc; + + let win = Arc::new(Mutex::new(window)); + + SetWindowLongPtrA(hwnd, GWLP_USERDATA, &Arc::clone(&win) as *const _ as _); + // todo: decide what to do with the message pump if parent.is_null() { loop { @@ -227,11 +249,11 @@ impl Window { // todo: pass callback rendering function instead gl::ClearColor(0.3, 0.8, 0.3, 1.0); gl::Clear(gl::COLOR_BUFFER_BIT); - SwapBuffers(window.hdc); + SwapBuffers(hdc); } } - window + win } } @@ -245,4 +267,8 @@ impl Window { unregister_wnd_class(self.window_class); } } + + pub(crate) fn handle_mouse_motion(&self, x: i32, y: i32) { + println!("{}, {}", x, y); + } }