Merge pull request #24 from MirkoCovizzi/issue-17+20
Windows: Refactor: move register window class into its own function
This commit is contained in:
commit
16363dcc4b
|
@ -4,8 +4,8 @@ use std::ffi::CString;
|
|||
use std::ptr::null_mut;
|
||||
|
||||
use self::winapi::shared::guiddef::GUID;
|
||||
use self::winapi::shared::minwindef::{LPARAM, LRESULT, UINT, WPARAM};
|
||||
use self::winapi::shared::windef::{HDC, HGLRC, HWND};
|
||||
use self::winapi::shared::minwindef::{ATOM, FALSE, LPARAM, LRESULT, UINT, WPARAM};
|
||||
use self::winapi::shared::windef::{HDC, HGLRC, HWND, RECT};
|
||||
use self::winapi::um::combaseapi::CoCreateGuid;
|
||||
use self::winapi::um::libloaderapi::{GetProcAddress, LoadLibraryA};
|
||||
use self::winapi::um::wingdi::{
|
||||
|
@ -14,11 +14,11 @@ use self::winapi::um::wingdi::{
|
|||
PFD_TYPE_RGBA, PIXELFORMATDESCRIPTOR,
|
||||
};
|
||||
use self::winapi::um::winuser::{
|
||||
CreateWindowExA, DefWindowProcA, DestroyWindow, DispatchMessageA, GetDC, MessageBoxA,
|
||||
PeekMessageA, PostQuitMessage, RegisterClassA, ReleaseDC, TranslateMessage, UnregisterClassA,
|
||||
CS_HREDRAW, CS_OWNDC, CS_VREDRAW, 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,
|
||||
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,
|
||||
};
|
||||
|
||||
use crate::Parent::WithParent;
|
||||
|
@ -49,151 +49,6 @@ unsafe fn generate_guid() -> String {
|
|||
)
|
||||
}
|
||||
|
||||
pub struct Window {
|
||||
hwnd: HWND,
|
||||
hdc: HDC,
|
||||
gl_context: HGLRC,
|
||||
class_name: *const i8,
|
||||
}
|
||||
|
||||
impl Window {
|
||||
// todo: we should decide this interface
|
||||
pub fn open(options: WindowOpenOptions) -> Self {
|
||||
unsafe {
|
||||
let mut hwnd = null_mut();
|
||||
let mut hdc = null_mut();
|
||||
let mut gl_context = null_mut();
|
||||
// We generate a unique name for the new window class to prevent name collisions
|
||||
let class_name = format!("Baseview-{}", generate_guid()).as_ptr() as *const i8;
|
||||
|
||||
let window = Window {
|
||||
hwnd,
|
||||
hdc,
|
||||
gl_context,
|
||||
class_name,
|
||||
};
|
||||
|
||||
let wnd_class = WNDCLASSA {
|
||||
style: CS_OWNDC | CS_HREDRAW | CS_VREDRAW,
|
||||
lpfnWndProc: Some(wnd_proc),
|
||||
hInstance: null_mut(),
|
||||
lpszClassName: class_name,
|
||||
cbClsExtra: 0,
|
||||
cbWndExtra: 0,
|
||||
hIcon: null_mut(),
|
||||
hCursor: null_mut(),
|
||||
hbrBackground: null_mut(),
|
||||
lpszMenuName: std::ptr::null::<i8>(),
|
||||
};
|
||||
|
||||
RegisterClassA(&wnd_class);
|
||||
|
||||
let mut flags = WS_POPUPWINDOW
|
||||
| WS_CAPTION
|
||||
| WS_VISIBLE
|
||||
| WS_SIZEBOX
|
||||
| WS_MINIMIZEBOX
|
||||
| WS_MAXIMIZEBOX
|
||||
| WS_CLIPSIBLINGS;
|
||||
|
||||
let mut parent = null_mut();
|
||||
if let WithParent(p) = options.parent {
|
||||
parent = p;
|
||||
flags = WS_CHILD | WS_VISIBLE;
|
||||
}
|
||||
|
||||
hwnd = CreateWindowExA(
|
||||
0,
|
||||
class_name,
|
||||
(options.title.to_owned() + "\0").as_ptr() as *const i8,
|
||||
flags,
|
||||
0,
|
||||
0,
|
||||
// todo: check if usize fits into i32
|
||||
options.width as i32,
|
||||
options.height as i32,
|
||||
parent as *mut _,
|
||||
null_mut(),
|
||||
null_mut(),
|
||||
null_mut(),
|
||||
);
|
||||
|
||||
hdc = GetDC(hwnd);
|
||||
|
||||
let mut pfd: PIXELFORMATDESCRIPTOR = std::mem::zeroed();
|
||||
pfd.nSize = std::mem::size_of::<PIXELFORMATDESCRIPTOR>() as u16;
|
||||
pfd.nVersion = 1;
|
||||
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
|
||||
pfd.iPixelType = PFD_TYPE_RGBA;
|
||||
pfd.cColorBits = 32;
|
||||
// todo: ask wrl why 24 instead of 32?
|
||||
pfd.cDepthBits = 24;
|
||||
pfd.cStencilBits = 8;
|
||||
pfd.iLayerType = PFD_MAIN_PLANE;
|
||||
|
||||
let pf_id: i32 = ChoosePixelFormat(hdc, &pfd);
|
||||
if pf_id == 0 {
|
||||
// todo: use a more useful return like an Option
|
||||
// todo: also launch error message boxes
|
||||
return window;
|
||||
}
|
||||
|
||||
if SetPixelFormat(hdc, pf_id, &pfd) == 0 {
|
||||
// todo: use a more useful return like an Option
|
||||
// todo: also launch error message boxes
|
||||
return window;
|
||||
}
|
||||
|
||||
gl_context = wglCreateContext(hdc);
|
||||
if gl_context == 0 as HGLRC {
|
||||
// todo: use a more useful return like an Option
|
||||
// todo: also launch error message boxes
|
||||
return window;
|
||||
}
|
||||
|
||||
if wglMakeCurrent(hdc, gl_context) == 0 {
|
||||
// todo: use a more useful return like an Option
|
||||
// todo: also launch error message boxes
|
||||
return window;
|
||||
}
|
||||
|
||||
let h = LoadLibraryA("opengl32.dll\0".as_ptr() as *const i8);
|
||||
gl::load_with(|symbol| {
|
||||
let symbol = CString::new(symbol.as_bytes()).unwrap();
|
||||
let symbol = symbol.as_ptr();
|
||||
GetProcAddress(h, symbol) as *const _
|
||||
});
|
||||
|
||||
// todo: decide what to do with the message pump
|
||||
if parent.is_null() {
|
||||
loop {
|
||||
if !handle_msg(null_mut()) {
|
||||
break;
|
||||
}
|
||||
|
||||
// todo: pass callback rendering function instead
|
||||
gl::ClearColor(0.3, 0.8, 0.3, 1.0);
|
||||
gl::Clear(gl::COLOR_BUFFER_BIT);
|
||||
SwapBuffers(hdc);
|
||||
}
|
||||
}
|
||||
|
||||
window
|
||||
}
|
||||
}
|
||||
|
||||
pub fn close(&self) {
|
||||
// todo: see https://github.com/wrl/rutabaga/blob/f30ff67e157375cafdbafe5fb549f1790443a3a8/src/platform/win/window.c#L402
|
||||
unsafe {
|
||||
wglMakeCurrent(null_mut(), null_mut());
|
||||
wglDeleteContext(self.gl_context);
|
||||
ReleaseDC(self.hwnd, self.hdc);
|
||||
DestroyWindow(self.hwnd);
|
||||
UnregisterClassA(self.class_name, null_mut());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_msg(_window: HWND) -> bool {
|
||||
unsafe {
|
||||
let mut msg: MSG = std::mem::zeroed();
|
||||
|
@ -224,3 +79,170 @@ unsafe extern "system" fn wnd_proc(
|
|||
}
|
||||
0
|
||||
}
|
||||
|
||||
unsafe fn register_wnd_class() -> ATOM {
|
||||
// We generate a unique name for the new window class to prevent name collisions
|
||||
let class_name = format!("Baseview-{}", generate_guid()).as_ptr() as *const i8;
|
||||
|
||||
let wnd_class = WNDCLASSA {
|
||||
style: CS_OWNDC,
|
||||
lpfnWndProc: Some(wnd_proc),
|
||||
hInstance: null_mut(),
|
||||
lpszClassName: class_name,
|
||||
cbClsExtra: 0,
|
||||
cbWndExtra: 0,
|
||||
hIcon: null_mut(),
|
||||
hCursor: null_mut(),
|
||||
hbrBackground: null_mut(),
|
||||
lpszMenuName: null_mut(),
|
||||
};
|
||||
|
||||
RegisterClassA(&wnd_class)
|
||||
}
|
||||
|
||||
unsafe fn unregister_wnd_class(wnd_class: ATOM) {
|
||||
UnregisterClassA(wnd_class as _, null_mut());
|
||||
}
|
||||
|
||||
unsafe fn init_gl_context() {}
|
||||
|
||||
pub struct Window {
|
||||
hwnd: HWND,
|
||||
hdc: HDC,
|
||||
gl_context: HGLRC,
|
||||
window_class: ATOM,
|
||||
}
|
||||
|
||||
impl Window {
|
||||
pub fn open(options: WindowOpenOptions) -> Self {
|
||||
unsafe {
|
||||
let mut window = Window {
|
||||
hwnd: null_mut(),
|
||||
hdc: null_mut(),
|
||||
gl_context: null_mut(),
|
||||
window_class: 0,
|
||||
};
|
||||
|
||||
let title = (options.title.to_owned() + "\0").as_ptr() as *const i8;
|
||||
|
||||
window.window_class = register_wnd_class();
|
||||
// todo: manage error ^
|
||||
|
||||
let mut flags = WS_POPUPWINDOW
|
||||
| WS_CAPTION
|
||||
| WS_VISIBLE
|
||||
| WS_SIZEBOX
|
||||
| WS_MINIMIZEBOX
|
||||
| WS_MAXIMIZEBOX
|
||||
| WS_CLIPSIBLINGS;
|
||||
|
||||
let mut rect = RECT {
|
||||
left: 0,
|
||||
top: 0,
|
||||
// todo: check if usize fits into i32
|
||||
right: options.width as i32,
|
||||
bottom: options.height as i32,
|
||||
};
|
||||
|
||||
// todo: add check flags https://github.com/wrl/rutabaga/blob/f30ff67e157375cafdbafe5fb549f1790443a3a8/src/platform/win/window.c#L351
|
||||
let mut parent = null_mut();
|
||||
if let WithParent(p) = options.parent {
|
||||
parent = p;
|
||||
flags = WS_CHILD | WS_VISIBLE;
|
||||
} else {
|
||||
AdjustWindowRectEx(&mut rect, flags, FALSE, 0);
|
||||
}
|
||||
|
||||
window.hwnd = CreateWindowExA(
|
||||
0,
|
||||
window.window_class as _,
|
||||
title,
|
||||
flags,
|
||||
0,
|
||||
0,
|
||||
rect.right - rect.left,
|
||||
rect.bottom - rect.top,
|
||||
parent as *mut _,
|
||||
null_mut(),
|
||||
null_mut(),
|
||||
null_mut(),
|
||||
);
|
||||
// todo: manage error ^
|
||||
|
||||
window.hdc = GetDC(window.hwnd);
|
||||
|
||||
//init_gl_context(&window, title);
|
||||
|
||||
let mut pfd: PIXELFORMATDESCRIPTOR = std::mem::zeroed();
|
||||
pfd.nSize = std::mem::size_of::<PIXELFORMATDESCRIPTOR>() as u16;
|
||||
pfd.nVersion = 1;
|
||||
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
|
||||
pfd.iPixelType = PFD_TYPE_RGBA;
|
||||
pfd.cColorBits = 32;
|
||||
// todo: ask wrl why 24 instead of 32?
|
||||
pfd.cDepthBits = 24;
|
||||
pfd.cStencilBits = 8;
|
||||
pfd.iLayerType = PFD_MAIN_PLANE;
|
||||
|
||||
let pf_id: i32 = ChoosePixelFormat(window.hdc, &pfd);
|
||||
if pf_id == 0 {
|
||||
// todo: use a more useful return like an Option
|
||||
// todo: also launch error message boxes
|
||||
return 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
let h = LoadLibraryA("opengl32.dll\0".as_ptr() as *const i8);
|
||||
gl::load_with(|symbol| {
|
||||
let symbol = CString::new(symbol.as_bytes()).unwrap();
|
||||
let symbol = symbol.as_ptr();
|
||||
GetProcAddress(h, symbol) as *const _
|
||||
});
|
||||
|
||||
// todo: decide what to do with the message pump
|
||||
if parent.is_null() {
|
||||
loop {
|
||||
if !handle_msg(null_mut()) {
|
||||
break;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
window
|
||||
}
|
||||
}
|
||||
|
||||
pub fn close(&self) {
|
||||
// todo: see https://github.com/wrl/rutabaga/blob/f30ff67e157375cafdbafe5fb549f1790443a3a8/src/platform/win/window.c#L402
|
||||
unsafe {
|
||||
wglMakeCurrent(null_mut(), null_mut());
|
||||
wglDeleteContext(self.gl_context);
|
||||
ReleaseDC(self.hwnd, self.hdc);
|
||||
DestroyWindow(self.hwnd);
|
||||
unregister_wnd_class(self.window_class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue