Fix for Windows.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m19s

This commit is contained in:
2025-01-26 16:57:27 -05:00
parent 3c4777c525
commit ff8fee6e90
5 changed files with 263 additions and 249 deletions

View File

@@ -27,9 +27,15 @@ CPMAddPackage(
)
#TODO dlopen these at runtime so if one isn't supported the program still works.
find_package(Vulkan REQUIRED)
include_directories(${Vulkan_INCLUDE_DIR})
if (UNIX AND NOT APPLE)
include_directories(${Vulkan_INCLUDE_DIR})
endif()
if (WIN32)
include_directories(${VULKAN_SDK}/Include)
endif()
include_directories(${J3ML_SOURCE_DIR}/include)
include_directories(${jlog_SOURCE_DIR}/include)
@@ -63,6 +69,7 @@ target_include_directories(ReWindow PUBLIC ${Event_SOURCE_DIR}/include)
set_target_properties(ReWindow PROPERTIES LINKER_LANGUAGE CXX)
if(UNIX AND NOT APPLE)
find_package(Vulkan REQUIRED)
target_link_libraries(ReWindow PUBLIC X11 Event jlog Vulkan::Vulkan)
target_link_libraries(ReWindow PUBLIC)
@@ -71,6 +78,7 @@ if(UNIX AND NOT APPLE)
endif()
if(WIN32)
find_package(OPENGL REQUIRED)
target_compile_options(ReWindow PUBLIC /utf-8)
target_link_libraries(ReWindow PUBLIC Event jlog ${OPENGL_LIBRARIES})
add_executable(ReWindowDemo main.cpp)

View File

@@ -0,0 +1,131 @@
#pragma once
#ifdef _WIN32
#include <ReWindow/types/Window.h>
using namespace ReWindow;
//Event loop.
// TODO move this. It can't be in the RWindow class because it has to be publicly visible.
inline LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
RWindow* window = reinterpret_cast<RWindow*>( GetWindowLongPtr(hwnd, GWLP_USERDATA) );
switch (uMsg) {
case WM_CLOSE: {
DestroyWindow(hwnd);
window->processOnClose();
}
case WM_DESTROY: {
exit(0);
}
case WM_SIZE: {
window->SetSizeWithoutEvent({ LOWORD(lParam), HIWORD(lParam) });
auto eventData = WindowResizeRequestEvent();
eventData.Size = { window->GetWidth(), window->GetHeight() };
window->SetLastKnownWindowSize({ window->GetWidth(), window->GetHeight() });
// TODO: Implement eWindow->processOnResize()
window->OnResizeRequest(eventData);
window->OnResizeRequestEvent(eventData);
break;
}
case WM_SETFOCUS: {
window->processFocusIn();
window->SetFlag(WindowFlag::IN_FOCUS, true);
break;
}
case WM_KILLFOCUS: {
window->processFocusOut();
window->SetFlag(WindowFlag::IN_FOCUS, false);
break;
}
case WM_SETCURSOR: {
if (LOWORD(lParam) == HTCLIENT && window->GetCursorVisible() == false)
SetCursor(nullptr);
break;
}
case WM_KEYDOWN: {
auto key = GetKeyFromWindowsScancode((WindowsScancode) wParam);
//Key repeat fix.
if (!window->previousKeyboard.PressedKeys[key])
window->processKeyPress(key);
break;
}
case WM_KEYUP: {
auto key = GetKeyFromWindowsScancode((WindowsScancode) wParam);
window->processKeyRelease(key);
break;
}
//Mouse Buttons.
case WM_MOUSEWHEEL: {
int wheel_delta = GET_WHEEL_DELTA_WPARAM(wParam);
// TODO: Determine sign of wheel_delta for each direction, (and on linux too), and document this.
window->processMouseWheel(wheel_delta);\
break;
}
case WM_LBUTTONDOWN: {
window->processMousePress(MouseButtons::Left);
break;
}
case WM_LBUTTONUP: {
window->processMouseRelease(MouseButtons::Left);
break;
}
case WM_RBUTTONDOWN: {
window->processMousePress(MouseButtons::Right);
break;
}
case WM_RBUTTONUP: {
window->processMouseRelease(MouseButtons::Right);
break;
}
case WM_MBUTTONDOWN: {
window->processMousePress(MouseButtons::Middle);
break;
}
case WM_MBUTTONUP: {
window->processMouseRelease(MouseButtons::Middle);
break;
}
case WM_XBUTTONDOWN: {
WORD button = GET_XBUTTON_WPARAM(wParam);
if (button == XBUTTON1)
window->processMousePress(MouseButtons::Mouse4);
if (button == XBUTTON2)
window->processMousePress(MouseButtons::Mouse5);
break;
}
case WM_XBUTTONUP: {
WORD button = GET_XBUTTON_WPARAM(wParam);
if (button == XBUTTON1)
window->processMouseRelease(MouseButtons::Mouse4);
if (button == XBUTTON2)
window->processMouseRelease(MouseButtons::Mouse5);
break;
}
//This is the same as "Motion Notify" in the X Window System.
case WM_MOUSEMOVE:
break;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
#endif

View File

@@ -72,6 +72,15 @@ public:
};
#endif
#ifdef _WIN32
#include <windows.h>
struct WIN32Vars {
HINSTANCE hInstance;
HWND hwnd;
HDC hdc;
};
#endif
/// RWindow is a class implementation of a platform-independent window abstraction.
/// This library also provides abstractions for user-input devices, and their interaction with the window.
class ReWindow::RWindow {
@@ -79,6 +88,11 @@ protected:
#ifdef __linux__
XVars xVars;
#endif
#ifdef _WIN32
WIN32Vars w32Vars;
#endif
int width = 1280;
int height = 720;
@@ -101,8 +115,6 @@ protected:
bool flags[5];
std::vector<RWindowEvent> eventLog; // history of all logged window events.
std::queue<RWindowEvent> eventQueue; //
KeyboardState currentKeyboard; // current frame keyboard state.
KeyboardState previousKeyboard; // previous frame keyboard state.
MouseState currentMouse; // purrent frame mouse state.
MouseState previousMouse; // previous frame mouse state
@@ -127,11 +139,13 @@ protected:
/// Requests the operating system to take the window out of fullscreen mode. Previously saved window size is restored, if possible.
void RestoreFromFullscreen();
public:
KeyboardState currentKeyboard; // current frame keyboard state.
KeyboardState previousKeyboard; // previous frame keyboard state.
// TODO: Josh hates parameter-flags, it's not 1995 :/
[[nodiscard]] bool GetFlag(WindowFlag flag) const;
void SetFlag(WindowFlag flag, bool state);
public:
/// The default constructor does not set any members, and are left uninitialized.
RWindow() = default;
/// Constructs a window by explicitly setting the title, width, height, and optionally; rendering API, fullscreen, resizable, and vsync.

View File

@@ -0,0 +1,75 @@
#include <ReWindow/types/Window.h>
#include <ReWindow/data/WindowsEventLoop.h>
#include <GL/gl.h>
using namespace ReWindow;
HGLRC glContext;
void OpenGLWindow::Open() {
w32Vars.hInstance = GetModuleHandle(nullptr);
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = w32Vars.hInstance;
wc.lpszClassName = "RWindowClass";
RegisterClass(&wc);
w32Vars.hwnd = CreateWindowEx(
0,
"RWindowClass",
title.c_str(),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, width, height,
nullptr,
nullptr,
w32Vars.hInstance,
nullptr
);
SetWindowLongPtr(w32Vars.hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
24,
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
24,
8,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0
};
w32Vars.hdc = GetDC(w32Vars.hwnd);
int pixelFormat = ChoosePixelFormat(w32Vars.hdc, &pfd);
SetPixelFormat(w32Vars.hdc, pixelFormat, &pfd);
glContext = wglCreateContext(w32Vars.hdc);
wglMakeCurrent(w32Vars.hdc, glContext);
ShowWindow(w32Vars.hwnd, SW_SHOW);
open = true;
}
std::string OpenGLWindow::GetGraphicsDriverVendor() {
return std::string(reinterpret_cast<const char*>(glGetString(GL_VENDOR)));
}
void OpenGLWindow::SwapBuffers() {
::SwapBuffers(w32Vars.hdc);
}
void OpenGLWindow::SetVsyncEnabled(bool b) {
typedef BOOL(WINAPI* PFNWGLSWAPINTERVALEXTPROC)(int interval);
auto wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) wglGetProcAddress("wglSwapIntervalEXT");
if (wglSwapIntervalEXT)
wglSwapIntervalEXT(b ? 1 : 0);
}
OpenGLWindow::OpenGLWindow(const std::string& title, int width, int height, uint8_t gl_major, uint8_t gl_minor)
: gl_major(gl_major), gl_minor(gl_minor), RWindow(title, width, height) {}

View File

@@ -1,33 +1,33 @@
#include <Windows.h>
#include <gl/GL.h>
#include <ReWindow/types/Window.h>
#include <rewindow/types/window.h>
using namespace ReWindow;
bool fullscreenmode = false;
bool open = false;
HINSTANCE hInstance = GetModuleHandle(nullptr);
HWND hwnd;
HDC hdc;
HGLRC glContext;
void raise() { SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); }
void lower() { SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); }
void RWindow::Raise() { SetWindowPos(w32Vars.hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); }
void RWindow::Lower() { SetWindowPos(w32Vars.hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); }
void RWindow::SetFlag(RWindowFlags flag, bool state) {
void RWindow::DestroyOSWindowHandle() {
DestroyWindow(w32Vars.hwnd);
}
void RWindow::SetFlag(WindowFlag flag, bool state) {
flags[(int) flag] = state;
if (flag == RWindowFlags::RESIZABLE && !state) {
if (flag == WindowFlag::RESIZABLE && !state) {
RECT rect;
GetWindowRect(hwnd, &rect);
LONG style = GetWindowLong(hwnd, GWL_STYLE);
GetWindowRect(w32Vars.hwnd, &rect);
LONG style = GetWindowLong(w32Vars.hwnd, GWL_STYLE);
style &= ~(WS_THICKFRAME | WS_MAXIMIZEBOX);
SetWindowLong(hwnd, GWL_STYLE, style);
SetWindowPos(hwnd, nullptr, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOOWNERZORDER);
SetWindowLong(w32Vars.hwnd, GWL_STYLE, style);
SetWindowPos(w32Vars.hwnd, nullptr, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOOWNERZORDER);
}
}
void RWindow::SetResizable(bool resizable) {
SetFlag(RWindowFlags::RESIZABLE, resizable);;
SetFlag(WindowFlag::RESIZABLE, resizable);;
}
@@ -41,16 +41,17 @@ void RWindow::PollEvents() {
void RWindow::SetSize(int newWidth, int newHeight) {
if (!resizable) return;
this->width = width;
this->height = height;
SetWindowPos(hwnd, nullptr, 0, 0, width, height, SWP_NOMOVE | SWP_NOZORDER);
this->width = newWidth;
this->height = newHeight;
SetWindowPos(w32Vars.hwnd, nullptr, 0, 0, width, height, SWP_NOMOVE | SWP_NOZORDER);
}
Vector2 RWindow::GetAccurateMouseCoordinates() const {
IPair RWindow::GetAccurateMouseCoordinates() const {
POINT point;
GetCursorPos(&point);
ScreenToClient(hwnd, &point);
return { (float)point.x, (float)point.y };
ScreenToClient(w32Vars.hwnd, &point);
return { point.x, point.y };
}
void RWindow::SetCursorVisible(bool cursor_enable) {
@@ -62,246 +63,31 @@ bool RWindow::GetCursorVisible() {
}
Vector2 RWindow::GetSize() const {
IPair RWindow::GetSize() const {
RECT rect;
GetClientRect(hwnd, &rect);
return { (float)(rect.right - rect.left), (float)(rect.bottom - rect.top) };
GetClientRect(w32Vars.hwnd, &rect);
return { (rect.right - rect.left), (rect.bottom - rect.top) };
}
void RWindow::SetPos(int x, int y) {
SetWindowPos(hwnd, nullptr, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
SetWindowPos(w32Vars.hwnd, nullptr, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
}
void RWindow::SetPos(const Vector2& pos) {
void RWindow::SetPos(const IPair& pos) {
SetPos(pos.x, pos.y);
}
void RWindow::Fullscreen() {
// Implement fullscreen
SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_OVERLAPPEDWINDOW);
SetWindowPos(hwnd, HWND_TOP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), SWP_FRAMECHANGED | SWP_NOOWNERZORDER);
SetWindowLong(w32Vars.hwnd, GWL_STYLE, GetWindowLong(w32Vars.hwnd, GWL_STYLE) & ~WS_OVERLAPPEDWINDOW);
SetWindowPos(w32Vars.hwnd, HWND_TOP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), SWP_FRAMECHANGED | SWP_NOOWNERZORDER);
}
void RWindow::RestoreFromFullscreen() {
// Implement restore from fullscreen
SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | WS_OVERLAPPEDWINDOW);
SetWindowPos(hwnd, nullptr, 0, 0, width, height, SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOOWNERZORDER);
}
void RWindow::SetVsyncEnabled(bool b) {
typedef BOOL(WINAPI* PFNWGLSWAPINTERVALEXTPROC)(int interval);
auto wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) wglGetProcAddress("wglSwapIntervalEXT");
if (wglSwapIntervalEXT)
wglSwapIntervalEXT(b ? 1 : 0);
}
RWindow* eWindow = nullptr;
KeyboardState* pKeyboard = nullptr;
KeyboardState* cKeyboard = nullptr;
//Event loop.
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_CLOSE: {
DestroyWindow(hwnd);
eWindow->processOnClose();
}
case WM_DESTROY: {
exit(0);
}
case WM_SIZE: {
eWindow->SetSizeWithoutEvent({(float) LOWORD(lParam), (float) HIWORD(lParam)});
auto eventData = WindowResizeRequestEvent();
eventData.Size = {(float) eWindow->GetWidth(), (float) eWindow->GetHeight()};
eWindow->SetLastKnownWindowSize({(float) eWindow->GetWidth(), (float) eWindow->GetHeight()});
// TODO: Implement eWindow->processOnResize()
eWindow->OnResizeRequest(eventData);
eWindow->OnResizeRequestEvent(eventData);
//Just to be absolutely sure the OpenGL viewport resizes along with the window.
glViewport(0, 0, eWindow->GetWidth(), eWindow->GetHeight());
break;
}
case WM_SETFOCUS: {
eWindow->processFocusIn();
eWindow->SetFlag(RWindowFlags::IN_FOCUS, true);
break;
}
case WM_KILLFOCUS: {
eWindow->processFocusOut();
eWindow->SetFlag(RWindowFlags::IN_FOCUS, false);
break;
}
case WM_SETCURSOR: {
if (LOWORD(lParam) == HTCLIENT && eWindow->GetCursorVisible() == false)
SetCursor(nullptr);
break;
}
case WM_KEYDOWN: {
auto key = GetKeyFromWindowsScancode((WindowsScancode) wParam);
//Key repeat fix.
if (!pKeyboard->PressedKeys[key]) {
eWindow->processKeyPress(key);
}
break;
}
case WM_KEYUP: {
auto key = GetKeyFromWindowsScancode((WindowsScancode) wParam);
eWindow->processKeyRelease(key);
break;
}
//Mouse Buttons.
case WM_MOUSEWHEEL: {
int wheel_delta = GET_WHEEL_DELTA_WPARAM(wParam);
// TODO: Determine sign of wheel_delta for each direction, (and on linux too), and document this.
eWindow->processMouseWheel(wheel_delta);
break;
}
case WM_LBUTTONDOWN: {
eWindow->processMousePress(MouseButtons::Left);
break;
}
case WM_LBUTTONUP: {
eWindow->processMouseRelease(MouseButtons::Left);
break;
}
case WM_RBUTTONDOWN: {
eWindow->processMousePress(MouseButtons::Right);
break;
}
case WM_RBUTTONUP: {
eWindow->processMouseRelease(MouseButtons::Right);
break;
}
case WM_MBUTTONDOWN: {
eWindow->processMousePress(MouseButtons::Middle);
break;
}
case WM_MBUTTONUP: {
eWindow->processMouseRelease(MouseButtons::Middle);
break;
}
case WM_XBUTTONDOWN: {
WORD button = GET_XBUTTON_WPARAM(wParam);
if (button == XBUTTON1)
eWindow->processMousePress(MouseButtons::Mouse4);
if (button == XBUTTON2)
eWindow->processMousePress(MouseButtons::Mouse5);
break;
}
case WM_XBUTTONUP: {
WORD button = GET_XBUTTON_WPARAM(wParam);
if (button == XBUTTON1)
eWindow->processMouseRelease(MouseButtons::Mouse4);
if (button == XBUTTON2)
eWindow->processMouseRelease(MouseButtons::Mouse5);
break;
}
//This is the same as "Motion Notify" in the X Window System.
case WM_MOUSEMOVE:
break;
}
if (pKeyboard != nullptr && cKeyboard != nullptr)
pKeyboard = cKeyboard;
return DefWindowProc(hwnd, uMsg, wParam, lParam);
SetWindowLong(w32Vars.hwnd, GWL_STYLE, GetWindowLong(w32Vars.hwnd, GWL_STYLE) | WS_OVERLAPPEDWINDOW);
SetWindowPos(w32Vars.hwnd, nullptr, 0, 0, width, height, SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOOWNERZORDER);
}
void RWindow::SetCursorStyle(CursorStyle style) const {}
void RWindow::Open() {
eWindow = this;
pKeyboard = &previousKeyboard;
cKeyboard = &currentKeyboard;
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = "RWindowClass";
RegisterClass(&wc);
hwnd = CreateWindowEx(
0,
"RWindowClass",
title.c_str(),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, width, height,
nullptr,
nullptr,
hInstance,
nullptr
);
if (renderer == RenderingAPI::OPENGL) {
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
24,
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
24,
8,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0
};
hdc = GetDC(hwnd);
int pixelFormat = ChoosePixelFormat(hdc, &pfd);
SetPixelFormat(hdc, pixelFormat, &pfd);
glContext = wglCreateContext(hdc);
wglMakeCurrent(hdc, glContext);
}
ShowWindow(hwnd, SW_SHOW);
open = true;
}
void RWindow::GLSwapBuffers() {
SwapBuffers(hdc);
}
std::string RWindow::getGraphicsDriverVendor() {
return std::string(reinterpret_cast<const char*>(glGetString(GL_VENDOR)));
}
void RWindow::DestroyOSWindowHandle() {
DestroyWindow(hwnd);
}