summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2025-02-22 10:27:03 -0500
committerAndrew Opalach <andrew@akon.city> 2025-02-22 10:27:03 -0500
commit1993433dc36dfae6a6c4b32f613e64ba213fdc23 (patch)
tree437168827e9e74d58c5f33481e9106b42a67759e /src
parentc0cd683e98f357d4b81cfd44444dbc909dcb2386 (diff)
downloadstela-1993433dc36dfae6a6c4b32f613e64ba213fdc23.tar.gz
stela-1993433dc36dfae6a6c4b32f613e64ba213fdc23.tar.bz2
stela-1993433dc36dfae6a6c4b32f613e64ba213fdc23.zip
Initial Windows window, refactor global_init()
Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'src')
-rw-r--r--src/window.h3
-rw-r--r--src/window_glfm.c5
-rw-r--r--src/window_glfw.c7
-rw-r--r--src/window_kms.c7
-rw-r--r--src/window_wayland.c4
-rw-r--r--src/window_win32.c355
-rw-r--r--src/window_win32.h19
-rw-r--r--src/window_x11.c4
8 files changed, 393 insertions, 11 deletions
diff --git a/src/window.h b/src/window.h
index 7c71056..7df00a3 100644
--- a/src/window.h
+++ b/src/window.h
@@ -16,6 +16,7 @@
#include <al/types.h>
#include <al/lib.h>
+#include <al/str.h>
#include <al/ring_buffer.h>
#if defined STELA_API_VULKAN
@@ -139,7 +140,7 @@ enum {
#endif
void stl_set_output_discovered_callback(void (*output_discovered)(void *, struct stl_monitor *), void *userdata);
-bool stl_global_init(bool skip_graphics);
+s32 stl_global_init(s32 argc, str *argv, s32 (*main)(s32, str *), bool skip_graphics);
s32 stl_global_get_poll_fd();
void stl_global_process_events();
void stl_global_close(void);
diff --git a/src/window_glfm.c b/src/window_glfm.c
index 29ab44b..7668eca 100644
--- a/src/window_glfm.c
+++ b/src/window_glfm.c
@@ -8,8 +8,11 @@ void stl_set_output_discovered_callback(void (*output_discovered)(void *, struct
(void)userdata;
}
-bool stl_global_init(bool skip_graphics)
+s32 stl_global_init(s32 argc, str *argv, s32 (*main)(s32, str *), bool skip_graphics)
{
+ (void)argc;
+ (void)argv;
+ (void)main;
(void)skip_graphics;
return false;
}
diff --git a/src/window_glfw.c b/src/window_glfw.c
index 836e7c8..bfd266f 100644
--- a/src/window_glfw.c
+++ b/src/window_glfw.c
@@ -36,16 +36,19 @@ static void error_callback(s32 error_code, const char *description)
al_log_error("glfw", "GLFW Error %d: %s.", error_code, description);
}
-bool stl_global_init(bool skip_graphics)
+s32 stl_global_init(s32 argc, str *argv, s32 (*main)(s32, str *), bool skip_graphics)
{
(void)skip_graphics;
+
glfwSetErrorCallback(error_callback);
if (!glfwInit()) {
al_log_error("glfw", "Failed to initialize GLFW.");
return false;
}
+
global.master_window = NULL;
- return true;
+
+ return main(argc, argv);
}
s32 stl_global_get_poll_fd()
diff --git a/src/window_kms.c b/src/window_kms.c
index 58d68eb..3a4e1a7 100644
--- a/src/window_kms.c
+++ b/src/window_kms.c
@@ -1,5 +1,3 @@
-#include <al/log.h>
-
#include "window_kms.h"
void stl_set_output_discovered_callback(void (*output_discovered)(void *, struct stl_monitor *), void *userdata)
@@ -8,8 +6,11 @@ void stl_set_output_discovered_callback(void (*output_discovered)(void *, struct
(void)userdata;
}
-bool stl_global_init(bool skip_graphics)
+s32 stl_global_init(s32 argc, str *argv, s32 (*main)(s32, str *), bool skip_graphics)
{
+ (void)argc;
+ (void)argv;
+ (void)main;
(void)skip_graphics;
return false;
}
diff --git a/src/window_wayland.c b/src/window_wayland.c
index 6935f0e..64177b9 100644
--- a/src/window_wayland.c
+++ b/src/window_wayland.c
@@ -127,7 +127,7 @@ void stl_set_output_discovered_callback(void (*output_discovered)(void *, struct
global.userdata = userdata;
}
-bool stl_global_init(bool skip_graphics)
+s32 stl_global_init(s32 argc, str *argv, s32 (*main)(s32, str *), bool skip_graphics)
{
global.display = wl_display_connect(NULL);
if (!global.display) {
@@ -164,7 +164,7 @@ bool stl_global_init(bool skip_graphics)
wl_display_roundtrip(global.display);
wl_display_roundtrip(global.display);
- return true;
+ return main(argc, argv);
}
s32 stl_global_get_poll_fd()
diff --git a/src/window_win32.c b/src/window_win32.c
new file mode 100644
index 0000000..5367c1a
--- /dev/null
+++ b/src/window_win32.c
@@ -0,0 +1,355 @@
+#include "window_win32.h"
+#include "common.h"
+
+// All extra Windows headers come after <nnwt/windows.h>.
+#include <windowsx.h>
+
+void stl_set_output_discovered_callback(void (*output_discovered)(void *, struct stl_monitor *), void *userdata)
+{
+ (void)output_discovered;
+ (void)userdata;
+}
+
+// https://github.com/cmuratori/dtc
+
+struct the_baby {
+ DWORD dwExStyle;
+ LPCWSTR lpClassName;
+ LPCWSTR lpWindowName;
+ DWORD dwStyle;
+ s32 X;
+ s32 Y;
+ s32 nWidth;
+ s32 nHeight;
+ HWND hWndParent;
+ HMENU hMenu;
+ HINSTANCE hInstance;
+ LPVOID lpParam;
+};
+
+#define CREATE_DANGEROUS_WINDOW (WM_USER + 0x1337)
+#define DESTROY_DANGEROUS_WINDOW (WM_USER + 0x1338)
+#define EXIT_PROCESS (WM_USER + 0x1339)
+#define WAKE_WINDOW (WM_USER + 0x133a)
+
+static DWORD MainThreadID;
+static struct stl_win32_global global;
+
+static LRESULT CALLBACK ServiceWndProc(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam)
+{
+ LRESULT Result = 0;
+
+ switch (Message) {
+ case CREATE_DANGEROUS_WINDOW: {
+ struct the_baby *Baby = (struct the_baby *)WParam;
+ Result = (LRESULT)CreateWindowExW(Baby->dwExStyle,
+ Baby->lpClassName,
+ Baby->lpWindowName,
+ Baby->dwStyle,
+ Baby->X,
+ Baby->Y,
+ Baby->nWidth,
+ Baby->nHeight,
+ Baby->hWndParent,
+ Baby->hMenu,
+ Baby->hInstance,
+ Baby->lpParam);
+ break;
+ }
+ case DESTROY_DANGEROUS_WINDOW:
+ DestroyWindow((HWND)WParam);
+ break;
+ case EXIT_PROCESS:
+ PostQuitMessage(WParam);
+ break;
+ default:
+ Result = DefWindowProcW(Window, Message, WParam, LParam);
+ break;
+ }
+
+ return Result;
+}
+
+static DWORD WINAPI MainThread(LPVOID Param)
+{
+ (void)Param;
+ s32 ret = global.main(global.argc, global.argv);
+ SendMessageW(global.ServiceWindow, EXIT_PROCESS, (WPARAM)ret, 0);
+ return 0;
+}
+
+s32 stl_global_init(s32 argc, str *argv, s32 (*main)(s32, str *), bool skip_graphics)
+{
+ (void)skip_graphics;
+
+ WNDCLASSEXW WindowClass = { 0 };
+ WindowClass.cbSize = sizeof(WindowClass);
+ WindowClass.lpfnWndProc = &ServiceWndProc;
+ WindowClass.hInstance = GetModuleHandleW(NULL);
+ WindowClass.hIcon = LoadIconA(NULL, IDI_APPLICATION);
+ WindowClass.hCursor = LoadCursorA(NULL, IDC_ARROW);
+ WindowClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
+ WindowClass.lpszClassName = L"DTCClass";
+ RegisterClassExW(&WindowClass);
+
+ global.ServiceWindow = CreateWindowExW(0, WindowClass.lpszClassName, L"DTCService", 0,
+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, WindowClass.hInstance, 0);
+ global.argc = argc;
+ global.argv = argv;
+ global.main = main;
+
+ CreateThread(0, 0, MainThread, NULL, 0, &MainThreadID);
+
+ for (;;) {
+ MSG Message;
+ GetMessageW(&Message, 0, 0, 0);
+ TranslateMessage(&Message);
+ if (Message.message == WM_QUIT) {
+ return Message.wParam;
+ }
+ DispatchMessageW(&Message);
+ }
+
+ return EXIT_FAILURE;
+}
+
+s32 stl_global_get_poll_fd()
+{
+ return -1;
+}
+
+void stl_global_process_events()
+{
+}
+
+void stl_global_close(void)
+{
+}
+
+static LRESULT CALLBACK DisplayWndProc(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam)
+{
+ LRESULT Result = 0;
+
+ /*
+ if (Message == WM_CREATE) {
+ SetWindowLongPtrA(Window, GWLP_USERDATA, (LONG_PTR)((LPCREATESTRUCT)LParam)->lpCreateParams);
+ return Result;
+ }
+ struct stl_window_win32 *w32 = (struct stl_window_win32 *)GetWindowLongPtrA(Window, GWLP_USERDATA);
+ */
+
+ switch (Message) {
+ case WM_CLOSE:
+ PostThreadMessageW(MainThreadID, Message, (WPARAM)Window, LParam);
+ break;
+ case WM_MOUSEMOVE:
+ case WM_MOUSEWHEEL:
+ case WM_KEYDOWN:
+ case WM_KEYUP:
+ case WM_LBUTTONDOWN:
+ case WM_LBUTTONUP:
+ case WM_SIZE:
+ PostThreadMessageW(MainThreadID, Message, WParam, LParam);
+ break;
+ default:
+ Result = DefWindowProcW(Window, Message, WParam, LParam);
+ break;
+ }
+
+ return Result;
+}
+
+static bool window_win32_create_window(struct stl_window *window, u32 width, u32 height,
+ const char *monitor, const char *name, u32 flags)
+{
+ struct stl_window_win32 *w32 = (struct stl_window_win32 *)window;
+ (void)monitor;
+ (void)flags;
+
+ w32->w.width = width;
+ w32->w.width = height;
+
+ WNDCLASSEXW WindowClass = { 0 };
+ WindowClass.cbSize = sizeof(WindowClass);
+ WindowClass.lpfnWndProc = &DisplayWndProc;
+ WindowClass.hInstance = GetModuleHandleW(NULL);
+ WindowClass.hIcon = LoadIconA(NULL, IDI_APPLICATION);
+ WindowClass.hCursor = LoadCursorA(NULL, IDC_ARROW);
+ WindowClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
+ WindowClass.lpszClassName = L"Dangerous Class";
+ RegisterClassExW(&WindowClass);
+
+ struct the_baby Baby = { 0 };
+ Baby.dwExStyle = 0;
+ Baby.lpClassName = WindowClass.lpszClassName;
+ al_wstr_from_cstr(&w32->WindowName, (char *)name);
+ Baby.lpWindowName = w32->WindowName.data;
+ Baby.dwStyle = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
+ Baby.X = CW_USEDEFAULT;
+ Baby.Y = CW_USEDEFAULT;
+ Baby.nWidth = width;
+ Baby.nHeight = height;
+ Baby.hInstance = WindowClass.hInstance;
+ Baby.lpParam = w32;
+ w32->Window = (HWND)SendMessageW(global.ServiceWindow, CREATE_DANGEROUS_WINDOW, (WPARAM)&Baby, 0);
+ w32->w.win32_window = w32->Window;
+
+ return true;
+}
+
+static void window_win32_resize_internal(struct stl_window *window, u32 width, u32 height)
+{
+ (void)window;
+ (void)width;
+ (void)height;
+}
+
+static void window_win32_resize(struct stl_window *window, u32 width, u32 height)
+{
+ (void)window;
+ (void)width;
+ (void)height;
+}
+
+static void window_win32_toggle_fullscreen(struct stl_window *window)
+{
+ (void)window;
+}
+
+static void win32_handle_message(struct stl_window_win32 *w32, MSG *Message)
+{
+ switch (Message->message) {
+ case WM_CLOSE:
+ stl_window_send_should_close_event(&w32->w);
+ break;
+ case WM_MOUSEMOVE:
+ stl_window_send_pointer_pos_event(&w32->w, (f64)GET_X_LPARAM(Message->lParam), (f64)GET_Y_LPARAM(Message->lParam));
+ break;
+ case WM_MOUSEWHEEL:
+ stl_window_send_scroll_event(&w32->w, -(f64)GET_WHEEL_DELTA_WPARAM(Message->wParam));
+ break;
+ case WM_KEYDOWN:
+ stl_window_send_key_event(&w32->w, STELA_BUTTON_PRESSED, Message->wParam);
+ break;
+ case WM_KEYUP:
+ stl_window_send_key_event(&w32->w, STELA_BUTTON_RELEASED, Message->wParam);
+ break;
+ case WM_LBUTTONDOWN:
+ stl_window_send_mouse_button_event(&w32->w, STELA_BUTTON_PRESSED, STELA_MOUSE1);
+ break;
+ case WM_LBUTTONUP:
+ stl_window_send_mouse_button_event(&w32->w, STELA_BUTTON_RELEASED, STELA_MOUSE1);
+ break;
+ case WM_SIZE:
+ w32->w.width = LOWORD(Message->lParam);
+ w32->w.height = HIWORD(Message->lParam);
+ stl_window_send_resize_event(&w32->w, w32->w.width, w32->w.height);
+ break;
+ case WAKE_WINDOW:
+ default:
+ break;
+ }
+}
+
+#ifdef STELA_POLL_INLINE
+static bool window_win32_poll(struct stl_window *window, bool block)
+{
+ struct stl_window_win32 *w32 = (struct stl_window_win32 *)window;
+ if (block) {
+ MSG Message;
+ GetMessageW(&Message, 0, 0, 0);
+ win32_handle_message(w32, &Message);
+ }
+ return true;
+}
+
+#ifdef STELA_PAUSE
+static void window_win32_wake(struct stl_window *window)
+{
+ (void)window;
+ PostThreadMessageW(MainThreadID, WAKE_WINDOW, 0, 0);
+}
+#endif
+#endif
+
+static void window_win32_process_events(struct stl_window *window)
+{
+ struct stl_window_win32 *w32 = (struct stl_window_win32 *)window;
+ MSG Message;
+ while (PeekMessage(&Message, 0, 0, 0, PM_REMOVE)) {
+ win32_handle_message(w32, &Message);
+ }
+}
+
+#ifdef STELA_PAUSE
+static bool window_win32_should_refresh(struct stl_window *window)
+{
+ return stl_should_refresh_common(window);
+}
+#endif
+
+static void window_win32_free(struct stl_window **window)
+{
+ struct stl_window_win32 *w32 = (struct stl_window_win32 *)window;
+ SendMessageW(global.ServiceWindow, DESTROY_DANGEROUS_WINDOW, (WPARAM)w32->Window, 0);
+ al_wstr_free(&w32->WindowName);
+}
+
+#if defined STELA_API_VULKAN
+#elif defined STELA_API_OPENGL
+static bool window_win32_gl_loader_load(void *data)
+{
+ (void)data;
+ return true;
+}
+
+static bool window_win32_gl_make_current(void *data)
+{
+ (void)data;
+ return true;
+}
+
+static void window_win32_gl_release_current(void *data)
+{
+ (void)data;
+}
+
+static void window_win32_gl_swap_buffers(void *data)
+{
+ struct stl_window_win32 *w32 = (struct stl_window_win32 *)data;
+ (void)w32;
+}
+#endif
+
+struct stl_window *stl_window_create(void *context)
+{
+ (void)context;
+ struct stl_window_win32 *w32 = al_alloc_object(struct stl_window_win32);
+ stl_window_common_init(&w32->w);
+ w32->w.fullscreen = true;
+ w32->w.create_window = window_win32_create_window;
+ w32->w.resize_internal = window_win32_resize_internal;
+ w32->w.resize = window_win32_resize;
+ w32->w.toggle_fullscreen = window_win32_toggle_fullscreen;
+#ifdef STELA_POLL_INLINE
+ w32->w.poll = window_win32_poll;
+#ifdef STELA_PAUSE
+ w32->w.wake = window_win32_wake;
+#endif
+#endif
+ w32->w.process_events = window_win32_process_events;
+#ifdef STELA_PAUSE
+ w32->w.should_refresh = window_win32_should_refresh;
+#endif
+ w32->w.free = window_win32_free;
+#if defined STELA_API_VULKAN
+#elif defined STELA_API_OPENGL
+ win32->w.get_gl_proc_address = NULL;
+ win32->w.gl_loader_load = window_win32_gl_loader_load;
+ win32->w.gl_make_current = window_win32_gl_make_current;
+ win32->w.gl_release_current = window_win32_gl_release_current;
+ win32->w.gl_swap_buffers = window_win32_gl_swap_buffers;
+#elif defined STELA_API_DX11
+#endif
+ return (struct stl_window *)w32;
+}
diff --git a/src/window_win32.h b/src/window_win32.h
new file mode 100644
index 0000000..59de230
--- /dev/null
+++ b/src/window_win32.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include <al/wstr.h>
+#include <nnwt/windows.h>
+
+#include "window.h"
+
+struct stl_win32_global {
+ HWND ServiceWindow;
+ s32 argc;
+ str *argv;
+ s32 (*main)(s32, str *);
+};
+
+struct stl_window_win32 {
+ struct stl_window w;
+ HWND Window;
+ wstr WindowName;
+};
diff --git a/src/window_x11.c b/src/window_x11.c
index c1425ee..f0a4559 100644
--- a/src/window_x11.c
+++ b/src/window_x11.c
@@ -21,7 +21,7 @@ void stl_set_output_discovered_callback(void (*output_discovered)(void *, struct
global.userdata = userdata;
}
-bool stl_global_init(bool skip_graphics)
+s32 stl_global_init(s32 argc, str *argv, s32 (*main)(s32, str *), bool skip_graphics)
{
global.x11_d = XOpenDisplay(NULL);
if (!global.x11_d) {
@@ -70,7 +70,7 @@ bool stl_global_init(bool skip_graphics)
}
XRRFreeMonitors(info);
- return true;
+ return main(argc, argv);
}
s32 stl_global_get_poll_fd()