273 lines
7.7 KiB
C
273 lines
7.7 KiB
C
#include "app.h"
|
|
#include "aio.h"
|
|
#include "buffer_manager.h"
|
|
#include "config.h"
|
|
#include "gfx.h"
|
|
#include "renderer_api.h"
|
|
|
|
extern void __RegisterRuntimeCVars(void);
|
|
|
|
VY_CVAR_I(rt_Fullscreen, "Show window in fullscreen mode. [0/1] Default: 0", 0);
|
|
VY_CVAR_I(rt_WindowWidth, "Window width. Default: 1024", 1024);
|
|
VY_CVAR_I(rt_WindowHeight, "Window height. Default: 768", 768);
|
|
|
|
#ifdef _WIN32
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#include <Windows.h>
|
|
|
|
static LRESULT CALLBACK win32WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
|
switch (uMsg) {
|
|
case WM_CLOSE:
|
|
PostQuitMessage(0);
|
|
return 0;
|
|
default:
|
|
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
|
|
}
|
|
}
|
|
|
|
VY_DLLEXPORT int
|
|
vyWin32Entry(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) {
|
|
|
|
__RegisterRuntimeCVars();
|
|
vyRegisterRendererCVars();
|
|
|
|
/* TODO: Parse the cvar config file */
|
|
|
|
if (vyInitBufferManager() != VY_SUCCESS) {
|
|
vyReportError("BUFFERMGR", "Init failed.");
|
|
return 1;
|
|
}
|
|
|
|
if (vyInitFileTab(1024) != VY_SUCCESS) {
|
|
vyReportError("FTAB", "Init failed.");
|
|
return 1;
|
|
}
|
|
|
|
if (vyInitAIO(0) != VY_SUCCESS) {
|
|
vyReportError("AIO", "Init failed.");
|
|
return 1;
|
|
}
|
|
|
|
WNDCLASSEXW wndclass = {
|
|
.cbSize = sizeof(wndclass),
|
|
.hInstance = hInstance,
|
|
.lpszClassName = L"vyWndClass",
|
|
.style = CS_OWNDC,
|
|
.lpfnWndProc = win32WndProc,
|
|
};
|
|
if (!RegisterClassExW(&wndclass)) {
|
|
vyReportError("CORE", "RegisterClassEx failed: %u", GetLastError());
|
|
return 1;
|
|
}
|
|
|
|
HWND wnd = NULL;
|
|
if (rt_Fullscreen.i) {
|
|
/* Fullscreen window */
|
|
int w = GetSystemMetrics(SM_CXSCREEN);
|
|
int h = GetSystemMetrics(SM_CYSCREEN);
|
|
wnd = CreateWindowExW(WS_EX_APPWINDOW,
|
|
L"vyWndClass",
|
|
L"Voyage",
|
|
WS_POPUP,
|
|
0,
|
|
0,
|
|
w,
|
|
h,
|
|
NULL,
|
|
NULL,
|
|
hInstance,
|
|
NULL);
|
|
ShowWindow(wnd, SW_SHOW);
|
|
} else {
|
|
/* Windowed mode */
|
|
int w = rt_WindowWidth.i;
|
|
int h = rt_WindowHeight.i;
|
|
wnd = CreateWindowExW(WS_EX_APPWINDOW,
|
|
L"vyWndClass",
|
|
L"Voyage",
|
|
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU,
|
|
CW_USEDEFAULT,
|
|
CW_USEDEFAULT,
|
|
w,
|
|
h,
|
|
NULL,
|
|
NULL,
|
|
hInstance,
|
|
NULL);
|
|
ShowWindow(wnd, SW_SHOW);
|
|
}
|
|
|
|
if (!wnd) {
|
|
vyReportError("CORE", "Failed to create the game window: %u", GetLastError());
|
|
return 1;
|
|
}
|
|
|
|
vy_renderer_init_info renderer_info = {.hWnd = wnd, .hInstance = hInstance};
|
|
if (!vyInitGFX(&renderer_info)) {
|
|
vyReportError("GFX", "Init failed.");
|
|
return 1;
|
|
}
|
|
|
|
/* Main Loop */
|
|
bool keep_running = true;
|
|
while (keep_running) {
|
|
MSG msg;
|
|
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) {
|
|
if (msg.message == WM_QUIT) {
|
|
keep_running = false;
|
|
} else {
|
|
TranslateMessage(&msg);
|
|
DispatchMessageW(&msg);
|
|
}
|
|
}
|
|
}
|
|
|
|
vyShutdownGFX();
|
|
|
|
DestroyWindow(wnd);
|
|
UnregisterClassW(L"vyWndClass", hInstance);
|
|
|
|
vyShutdownAIO();
|
|
vyShutdownAIO();
|
|
vyShutdownFileTab();
|
|
vyShutdownBufferManager();
|
|
|
|
return 0;
|
|
}
|
|
|
|
#elif defined(VY_USE_XLIB)
|
|
|
|
#include <X11/Xlib.h>
|
|
#include <assert.h>
|
|
|
|
static void xlibSetFullscreen(Display *dpy, int screen, Window window, bool enable) {
|
|
Atom wm_state = XInternAtom(dpy, "_NET_W_STATE", False);
|
|
Atom wm_fullscreen = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
|
|
if (wm_state == None || wm_fullscreen == None) {
|
|
vyLog("CORE", "Window manager does not support fullscreen mode.");
|
|
return;
|
|
}
|
|
|
|
#define _NET_WM_STATE_REMOVE 0
|
|
#define _NET_WM_STATE_ADD 1
|
|
#define EVENT_SOURCE_APPLICATION 1
|
|
XEvent ev;
|
|
ev.type = ClientMessage;
|
|
ev.xclient.display = dpy;
|
|
ev.xclient.window = window;
|
|
ev.xclient.message_type = wm_state;
|
|
ev.xclient.format = 32;
|
|
ev.xclient.data.l[0] = (enable) ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
|
|
ev.xclient.data.l[1] = wm_fullscreen;
|
|
ev.xclient.data.l[2] = 0;
|
|
ev.xclient.data.l[3] = EVENT_SOURCE_APPLICATION;
|
|
ev.xclient.data.l[4] = 0;
|
|
|
|
Window root_window = XRootWindow(dpy, screen);
|
|
long ev_mask = SubstructureRedirectMask;
|
|
|
|
if (!XSendEvent(dpy, root_window, False, ev_mask, &ev)) {
|
|
vyReportError("CORE", "Failed to send x11 fullscreen event.");
|
|
}
|
|
|
|
#undef _NET_WM_STATE_ADD
|
|
#undef _NET_WM_STATE_REMOVE
|
|
#undef EVENT_SOURCE_APPLICATION
|
|
}
|
|
|
|
VY_DLLEXPORT int vyXlibEntry(int argc, char **argv) {
|
|
__RegisterRuntimeCVars();
|
|
vyRegisterRendererCVars();
|
|
|
|
if (vyInitBufferManager() != VY_SUCCESS) {
|
|
vyReportError("BUFFERMGR", "Init failed.");
|
|
return 1;
|
|
}
|
|
|
|
if (vyInitFileTab(1024) != VY_SUCCESS) {
|
|
vyReportError("FTAB", "Init failed.");
|
|
return 1;
|
|
}
|
|
|
|
if (vyInitAIO(0) != VY_SUCCESS) {
|
|
vyReportError("AIO", "Init failed.");
|
|
return 1;
|
|
}
|
|
|
|
Display *dpy = XOpenDisplay(NULL);
|
|
if (!dpy) {
|
|
vyReportError("CORE", "Failed to open default display");
|
|
return 1;
|
|
}
|
|
int screen = DefaultScreen(dpy);
|
|
Window window;
|
|
int w = rt_WindowWidth.i;
|
|
int h = rt_WindowHeight.i;
|
|
window = XCreateSimpleWindow(dpy,
|
|
RootWindow(dpy, screen),
|
|
10,
|
|
10,
|
|
w,
|
|
h,
|
|
1,
|
|
BlackPixel(dpy, screen),
|
|
WhitePixel(dpy, screen));
|
|
XSelectInput(dpy, window, KeyPressMask);
|
|
XMapWindow(dpy, window);
|
|
XStoreName(dpy, window, "Voyage");
|
|
|
|
Atom wm_close = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
|
|
if (!wm_close) {
|
|
vyReportError("CORE", "Failed to find WM_DELETE_WINDOW atom.");
|
|
XDestroyWindow(dpy, window);
|
|
XCloseDisplay(dpy);
|
|
return 1;
|
|
}
|
|
XSetWMProtocols(dpy, window, &wm_close, 1);
|
|
|
|
if (rt_Fullscreen.i)
|
|
xlibSetFullscreen(dpy, screen, window, true);
|
|
|
|
vy_renderer_init_info renderer_info = {.display = dpy, .window = window};
|
|
if (!vyInitGFX(&renderer_info)) {
|
|
vyReportError("GFX", "Init failed.");
|
|
return 1;
|
|
}
|
|
|
|
/* Main Loop */
|
|
bool keep_running = true;
|
|
while (keep_running) {
|
|
while (XEventsQueued(dpy, QueuedAlready) > 0) {
|
|
XEvent event;
|
|
XNextEvent(dpy, &event);
|
|
switch (event.type) {
|
|
case KeyPress:
|
|
break;
|
|
case ButtonPressMask:
|
|
/* Mouse down */
|
|
break;
|
|
case PointerMotionMask:
|
|
/* Mouse movement */
|
|
break;
|
|
case ClientMessage:
|
|
if (event.xclient.data.l[0] == (long)wm_close) {
|
|
vyLog("CORE", "Received WM_DELETE_WINDOW");
|
|
keep_running = false;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
vyShutdownGFX();
|
|
XDestroyWindow(dpy, window);
|
|
XCloseDisplay(dpy);
|
|
vyShutdownAIO();
|
|
vyShutdownFileTab();
|
|
vyShutdownBufferManager();
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif
|