fixed gitignore
This commit is contained in:
parent
8c26c11e0d
commit
68404e7535
256
src/os/win32/os_core_win32.c
Normal file
256
src/os/win32/os_core_win32.c
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//~
|
||||||
|
|
||||||
|
#pragma comment(lib, "kernel32")
|
||||||
|
#pragma comment(lib, "user32")
|
||||||
|
#pragma comment(lib, "gdi32")
|
||||||
|
|
||||||
|
|
||||||
|
#define OS_W32_MSG_CREATE_WINDOW (WM_USER + 0x1337)
|
||||||
|
#define OS_W32_MSG_DESTROY_WINDOW (WM_USER + 0x1338)
|
||||||
|
global DWORD MainThreadID;
|
||||||
|
global HWND g_service_window_handle;
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//~
|
||||||
|
|
||||||
|
internal void *
|
||||||
|
os_reserve(U64 size)
|
||||||
|
{
|
||||||
|
void *result = VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal B32
|
||||||
|
os_commit(void *ptr, U64 size)
|
||||||
|
{
|
||||||
|
B32 result = (VirtualAlloc(ptr, size, MEM_COMMIT, PAGE_READWRITE) != 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
os_decommit(void *ptr, U64 size)
|
||||||
|
{
|
||||||
|
VirtualFree(ptr, size, MEM_DECOMMIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
os_release(void *ptr, U64 size)
|
||||||
|
{
|
||||||
|
// NOTE(anton): Don't need to use size for freeing on Win32, but the API
|
||||||
|
// should have it for other platforms.
|
||||||
|
VirtualFree(ptr, 0, MEM_RELEASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//~
|
||||||
|
|
||||||
|
internal LRESULT CALLBACK
|
||||||
|
ServiceWndProc(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam)
|
||||||
|
{
|
||||||
|
/* NOTE(casey): This is not really a window handler per se, it's actually just
|
||||||
|
a remote thread call handler. Windows only really has blocking remote thread
|
||||||
|
calls if you register a WndProc for them, so that's what we do.
|
||||||
|
|
||||||
|
This handles CREATE_DANGEROUS_WINDOW and DESTROY_DANGEROUS_WINDOW, which are
|
||||||
|
just calls that do CreateWindow and DestroyWindow here on this thread when
|
||||||
|
some other thread wants that to happen.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LRESULT result = 0;
|
||||||
|
|
||||||
|
switch(Message)
|
||||||
|
{
|
||||||
|
case OS_W32_MSG_CREATE_WINDOW:
|
||||||
|
{
|
||||||
|
OS_W32_WndParam *wndParam = (OS_W32_WndParam *)WParam;
|
||||||
|
result = (LRESULT)CreateWindowExW(wndParam->dwExStyle,
|
||||||
|
wndParam->lpClassName,
|
||||||
|
wndParam->lpWindowName,
|
||||||
|
wndParam->dwStyle,
|
||||||
|
wndParam->X,
|
||||||
|
wndParam->Y,
|
||||||
|
wndParam->nWidth,
|
||||||
|
wndParam->nHeight,
|
||||||
|
wndParam->hWndParent,
|
||||||
|
wndParam->hMenu,
|
||||||
|
wndParam->hInstance,
|
||||||
|
wndParam->lpParam);
|
||||||
|
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case OS_W32_MSG_DESTROY_WINDOW:
|
||||||
|
{
|
||||||
|
DestroyWindow((HWND)WParam);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
result = DefWindowProcW(Window, Message, WParam, LParam);
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal LRESULT CALLBACK
|
||||||
|
DisplayWndProc(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam)
|
||||||
|
{
|
||||||
|
/* NOTE(casey): This is an example of an actual window procedure. It doesn't do anything
|
||||||
|
but forward things to the main thread, because again, all window messages now occur
|
||||||
|
on the message thread, and presumably we would rather handle everything there. You
|
||||||
|
don't _have_ to do that - you could choose to handle some of the messages here.
|
||||||
|
But if you did, you would have to actually think about whether there are race conditions
|
||||||
|
with your main thread and all that. So just PostThreadMessageW()'ing everything gets
|
||||||
|
you out of having to think about it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LRESULT Result = 0;
|
||||||
|
|
||||||
|
switch (Message)
|
||||||
|
{
|
||||||
|
// NOTE(casey): Mildly annoying, if you want to specify a window, you have
|
||||||
|
// to snuggle the params yourself, because Windows doesn't let you forward
|
||||||
|
// a god damn window message even though the program IS CALLED WINDOWS. It's
|
||||||
|
// in the name! Let me pass it!
|
||||||
|
case WM_CLOSE:
|
||||||
|
{
|
||||||
|
PostThreadMessageW(MainThreadID, Message, (WPARAM)Window, LParam);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
// NOTE(casey): Anything you want the application to handle, forward to the main thread
|
||||||
|
// here.
|
||||||
|
case WM_MOUSEMOVE:
|
||||||
|
case WM_LBUTTONDOWN:
|
||||||
|
case WM_LBUTTONUP:
|
||||||
|
case WM_DESTROY:
|
||||||
|
case WM_CHAR:
|
||||||
|
{
|
||||||
|
PostThreadMessageW(MainThreadID, Message, WParam, LParam);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
Result = DefWindowProcW(Window, Message, WParam, LParam);
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal DWORD WINAPI
|
||||||
|
MainThreadEntryPoint(LPVOID Param)
|
||||||
|
{
|
||||||
|
/* NOTE(Casey): This is your app code. Basically you just do everything the same,
|
||||||
|
but instead of calling CreateWindow/DestroyWindow, you use SendMessage to
|
||||||
|
do it on the other thread, using the CREATE_DANGEROUS_WINDOW and DESTROY_DANGEROUS_WINDOW
|
||||||
|
user messages. Otherwise, everything proceeds as normal.
|
||||||
|
*/
|
||||||
|
HWND ServiceWindow = (HWND)Param;
|
||||||
|
g_service_window_handle = ServiceWindow;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
OS_W32_WndParam wndParam = {0};
|
||||||
|
wndParam.dwExStyle = 0;;
|
||||||
|
wndParam.lpClassName = WindowClass.lpszClassName;
|
||||||
|
wndParam.lpWindowName = L"Dangerous Window";
|
||||||
|
wndParam.dwStyle = WS_OVERLAPPEDWINDOW|WS_VISIBLE;
|
||||||
|
wndParam.X = CW_USEDEFAULT;
|
||||||
|
wndParam.Y = CW_USEDEFAULT;
|
||||||
|
wndParam.nWidth = CW_USEDEFAULT;
|
||||||
|
wndParam.nHeight = CW_USEDEFAULT;
|
||||||
|
wndParam.hInstance = WindowClass.hInstance;
|
||||||
|
|
||||||
|
// Create initial window
|
||||||
|
HWND ThisWouldBeTheHandleIfYouCared = (HWND)SendMessageW(ServiceWindow,
|
||||||
|
OS_W32_MSG_CREATE_WINDOW,
|
||||||
|
(WPARAM)&wndParam,
|
||||||
|
0);
|
||||||
|
|
||||||
|
entry_point();
|
||||||
|
|
||||||
|
|
||||||
|
LOG("Exited main program. Terminating \n");
|
||||||
|
ExitProcess(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* NOTE(casey): At startup, you create one hidden window used to handle requests
|
||||||
|
to create or destroy windows. There's nothing special about this window; it
|
||||||
|
only exists because Windows doesn't have a way to do a remote thread call without
|
||||||
|
a window handler. You could instead just do this with your own synchronization
|
||||||
|
primitives if you wanted - this is just the easiest way to do it on Windows
|
||||||
|
because they've already built it for you.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOG("Entered WinMain\n");
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
HWND ServiceWindow = CreateWindowExW(0, WindowClass.lpszClassName, L"DTCService", 0,
|
||||||
|
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||||
|
0, 0, WindowClass.hInstance, 0);
|
||||||
|
|
||||||
|
// NOTE(casey): Once the service window is created, you can start the main thread,
|
||||||
|
// which is where all your app code would actually happen.
|
||||||
|
CreateThread(0, 0, MainThreadEntryPoint, ServiceWindow, 0, &MainThreadID);
|
||||||
|
|
||||||
|
// NOTE(casey): This thread can just idle for the rest of the run, forwarding
|
||||||
|
// messages to the main thread that it thinks the main thread wants.
|
||||||
|
DWORD exitCode;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
|
||||||
|
MSG Message;
|
||||||
|
GetMessageW(&Message, 0, 0, 0);
|
||||||
|
TranslateMessage(&Message);
|
||||||
|
if((Message.message == WM_CHAR) ||
|
||||||
|
(Message.message == WM_KEYDOWN) ||
|
||||||
|
(Message.message == WM_QUIT) ||
|
||||||
|
(Message.message == WM_SIZE))
|
||||||
|
{
|
||||||
|
PostThreadMessageW(MainThreadID, Message.message, Message.wParam, Message.lParam);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DispatchMessageW(&Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal void
|
||||||
|
OS_W32_log_debug(const char *fmt_string, ...)
|
||||||
|
{
|
||||||
|
char buffer[1024];
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt_string);
|
||||||
|
_vsnprintf(buffer, sizeof(buffer) / sizeof(char), fmt_string, args);
|
||||||
|
va_end(args);
|
||||||
|
OutputDebugStringA(buffer);
|
||||||
|
}
|
||||||
31
src/os/win32/os_core_win32.h
Normal file
31
src/os/win32/os_core_win32.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef OS_CORE_WIN32_H
|
||||||
|
#define OS_CORE_WIN32_H
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//~
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
// Temp struct for launching window on separate thread.
|
||||||
|
// Trying to learn from https://github.com/cmuratori/dtc/blob/main/dtc.cpp
|
||||||
|
typedef struct OS_W32_WndParam OS_W32_WndParam;
|
||||||
|
struct OS_W32_WndParam
|
||||||
|
{
|
||||||
|
DWORD dwExStyle;
|
||||||
|
LPCWSTR lpClassName;
|
||||||
|
LPCWSTR lpWindowName;
|
||||||
|
DWORD dwStyle;
|
||||||
|
S32 X;
|
||||||
|
S32 Y;
|
||||||
|
S32 nWidth;
|
||||||
|
S32 nHeight;
|
||||||
|
HWND hWndParent;
|
||||||
|
HMENU hMenu;
|
||||||
|
HINSTANCE hInstance;
|
||||||
|
LPVOID lpParam;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
internal void OS_W32_log_debug(const char *fmt_string, ...);
|
||||||
|
|
||||||
|
#endif /* OS_CORE_WIN32_H */
|
||||||
Loading…
Reference in New Issue
Block a user