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