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 std::ptr::null_mut;
|
||||||
|
|
||||||
use self::winapi::shared::guiddef::GUID;
|
use self::winapi::shared::guiddef::GUID;
|
||||||
use self::winapi::shared::minwindef::{LPARAM, LRESULT, UINT, WPARAM};
|
use self::winapi::shared::minwindef::{ATOM, FALSE, LPARAM, LRESULT, UINT, WPARAM};
|
||||||
use self::winapi::shared::windef::{HDC, HGLRC, HWND};
|
use self::winapi::shared::windef::{HDC, HGLRC, HWND, RECT};
|
||||||
use self::winapi::um::combaseapi::CoCreateGuid;
|
use self::winapi::um::combaseapi::CoCreateGuid;
|
||||||
use self::winapi::um::libloaderapi::{GetProcAddress, LoadLibraryA};
|
use self::winapi::um::libloaderapi::{GetProcAddress, LoadLibraryA};
|
||||||
use self::winapi::um::wingdi::{
|
use self::winapi::um::wingdi::{
|
||||||
|
@ -14,11 +14,11 @@ use self::winapi::um::wingdi::{
|
||||||
PFD_TYPE_RGBA, PIXELFORMATDESCRIPTOR,
|
PFD_TYPE_RGBA, PIXELFORMATDESCRIPTOR,
|
||||||
};
|
};
|
||||||
use self::winapi::um::winuser::{
|
use self::winapi::um::winuser::{
|
||||||
CreateWindowExA, DefWindowProcA, DestroyWindow, DispatchMessageA, GetDC, MessageBoxA,
|
AdjustWindowRectEx, CreateWindowExA, DefWindowProcA, DestroyWindow, DispatchMessageA, GetDC,
|
||||||
PeekMessageA, PostQuitMessage, RegisterClassA, ReleaseDC, TranslateMessage, UnregisterClassA,
|
MessageBoxA, PeekMessageA, PostQuitMessage, RegisterClassA, ReleaseDC, TranslateMessage,
|
||||||
CS_HREDRAW, CS_OWNDC, CS_VREDRAW, MB_ICONERROR, MB_OK, MB_TOPMOST, MSG, PM_REMOVE, WM_CLOSE,
|
UnregisterClassA, CS_OWNDC, MB_ICONERROR, MB_OK, MB_TOPMOST, MSG,
|
||||||
WM_QUIT, WNDCLASSA, WS_CAPTION, WS_CHILD, WS_CLIPSIBLINGS, WS_MAXIMIZEBOX, WS_MINIMIZEBOX,
|
PM_REMOVE, WM_CLOSE, WM_QUIT, WNDCLASSA, WS_CAPTION, WS_CHILD, WS_CLIPSIBLINGS, WS_MAXIMIZEBOX,
|
||||||
WS_POPUPWINDOW, WS_SIZEBOX, WS_VISIBLE,
|
WS_MINIMIZEBOX, WS_POPUPWINDOW, WS_SIZEBOX, WS_VISIBLE,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::Parent::WithParent;
|
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 {
|
fn handle_msg(_window: HWND) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut msg: MSG = std::mem::zeroed();
|
let mut msg: MSG = std::mem::zeroed();
|
||||||
|
@ -224,3 +79,170 @@ unsafe extern "system" fn wnd_proc(
|
||||||
}
|
}
|
||||||
0
|
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