356 lines
7.2 KiB
C
356 lines
7.2 KiB
C
// TODO(MA): Do stuff for general unix platforms some day
|
|
|
|
static Window linux_window = {
|
|
.w = 1920,
|
|
.h = 1080,
|
|
};
|
|
|
|
// Init
|
|
|
|
b32 _LoadLib(const char *name, Library *out_lib)
|
|
{
|
|
if (!name) {
|
|
return false;
|
|
}
|
|
|
|
out_lib->lib = dlopen(name, RTLD_NOW);
|
|
if (!out_lib->lib) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
b32 _LoadFn(const char *name, Library *lib, Function *out_fn)
|
|
{
|
|
if (!name) {
|
|
return false;
|
|
}
|
|
|
|
out_fn->fn = dlsym(lib->lib, name);
|
|
if (!out_fn->fn) {
|
|
Printf("unable to find function\n");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
b32 _InitPlatform()
|
|
{
|
|
return true;
|
|
}
|
|
// Init End
|
|
|
|
// General Utils
|
|
b32 CheckSyscallErr(void *ptr)
|
|
{
|
|
return (isize)ptr == SYS_ERR ? true : false;
|
|
}
|
|
// General Utils End
|
|
|
|
i32 Write(int fd, void const *str, isize count)
|
|
{
|
|
i32 result = (i32)write(fd, str, count);
|
|
return result;
|
|
}
|
|
|
|
i32 _EPrint(void const *str)
|
|
{
|
|
return Write(_STDERR, str, (isize)StrLen(str));
|
|
}
|
|
|
|
i32 _EPrintf(const char *fmt, va_list arg)
|
|
{
|
|
char buffer[1024];
|
|
|
|
int sprf_res = stbsp_vsnprintf(&buffer[0], 1024, fmt, arg);
|
|
|
|
if (sprf_res < 0) return sprf_res;
|
|
i32 pr_res = EPrint(&buffer);
|
|
|
|
return pr_res;
|
|
}
|
|
|
|
i32 _Printf(const char *fmt, va_list arg)
|
|
{
|
|
char buffer[1024];
|
|
|
|
int sprf_res = stbsp_vsnprintf(&buffer[0], 1024, fmt, arg);
|
|
|
|
i32 pr_res;
|
|
if (sprf_res < 0)
|
|
pr_res = sprf_res;
|
|
else
|
|
pr_res = Write(_STDOUT, &buffer, sprf_res);
|
|
|
|
return pr_res;
|
|
}
|
|
|
|
i32 _Printfln(const char *fmt, va_list arg)
|
|
{
|
|
char buffer[1024];
|
|
|
|
int sprf_res = stbsp_vsnprintf(&buffer[0], 1023, fmt, arg);
|
|
|
|
i32 pr_res;
|
|
if (sprf_res < 0)
|
|
{
|
|
pr_res = sprf_res;
|
|
}
|
|
else
|
|
{
|
|
buffer[sprf_res] = '\n';
|
|
buffer[sprf_res+1] = '\0';
|
|
pr_res = Write(_STDOUT, &buffer, sprf_res+1);
|
|
}
|
|
|
|
return pr_res;
|
|
}
|
|
|
|
rawptr _MemAlloc(isize size)
|
|
{
|
|
void *addr = mmap(
|
|
NULL,
|
|
size,
|
|
PROT_READ | PROT_WRITE,
|
|
MAP_ANON | MAP_PRIVATE,
|
|
-1,
|
|
0
|
|
);
|
|
|
|
if (CheckSyscallErr(addr)) addr = NULL;
|
|
|
|
return addr;
|
|
}
|
|
|
|
rawptr _MemAllocZeroed(isize size)
|
|
{
|
|
rawptr ptr = MemAlloc(size);
|
|
MemZero(ptr, size);
|
|
return ptr;
|
|
}
|
|
|
|
isize _GetPageSize()
|
|
{
|
|
return (isize)sysconf(_SC_PAGESIZE);
|
|
}
|
|
|
|
b32 _CreateWindow()
|
|
{
|
|
Window *window = &linux_window;
|
|
|
|
int screen_index;
|
|
window->connection = xcb_connect(NULL, &screen_index);
|
|
|
|
if (!window->connection) {
|
|
return false;
|
|
}
|
|
|
|
xcb_void_cookie_t cookie;
|
|
xcb_generic_error_t *error;
|
|
|
|
const xcb_setup_t *setup = xcb_get_setup(window->connection);
|
|
xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup);
|
|
xcb_screen_t *screen = iter.data;
|
|
|
|
const int event_mask = XCB_EVENT_MASK_EXPOSURE |
|
|
XCB_EVENT_MASK_KEY_PRESS |
|
|
XCB_EVENT_MASK_KEY_RELEASE |
|
|
XCB_EVENT_MASK_BUTTON_PRESS |
|
|
XCB_EVENT_MASK_BUTTON_RELEASE |
|
|
XCB_EVENT_MASK_POINTER_MOTION |
|
|
XCB_EVENT_MASK_STRUCTURE_NOTIFY;
|
|
|
|
const int val_win[] = {screen->black_pixel, event_mask};
|
|
const int val_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
|
|
|
|
window->window = xcb_generate_id(window->connection);
|
|
|
|
cookie = xcb_create_window(
|
|
window->connection,
|
|
XCB_COPY_FROM_PARENT,
|
|
window->window,
|
|
screen->root,
|
|
0, // x pos
|
|
0, // y pos
|
|
window->w, // width
|
|
window->h, // height
|
|
0,
|
|
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
|
screen->root_visual,
|
|
val_mask,
|
|
val_win
|
|
);
|
|
XCB_CHECK_ERROR(window, cookie, error, "Failed to create window.");
|
|
|
|
cookie = xcb_map_window_checked(window->connection, window->window);
|
|
XCB_CHECK_ERROR(window, cookie, error, "Failed to map window.");
|
|
|
|
cookie = xcb_change_property_checked(
|
|
window->connection,
|
|
XCB_PROP_MODE_REPLACE,
|
|
window->window,
|
|
XCB_ATOM_WM_NAME,
|
|
XCB_ATOM_STRING,
|
|
8,
|
|
StrLen(WINDOW_NAME),
|
|
WINDOW_NAME
|
|
);
|
|
XCB_CHECK_ERROR(window, cookie, error, "Failed to rename window.");
|
|
|
|
xcb_intern_atom_cookie_t c_proto = xcb_intern_atom(window->connection, 1, 12, "WM_PROTOCOLS");
|
|
xcb_intern_atom_reply_t *r_proto = xcb_intern_atom_reply(window->connection, c_proto, &error);
|
|
XCB_CHECK_CURRENT_ERROR(window, error, "Failed to get WM_PROTOCOLS.");
|
|
|
|
xcb_intern_atom_cookie_t c_close = xcb_intern_atom(window->connection, 0, 16, "WM_DELETE_WINDOW");
|
|
xcb_intern_atom_reply_t *r_close = xcb_intern_atom_reply(window->connection, c_close, &error);
|
|
XCB_CHECK_CURRENT_ERROR(window, error, "Failed to get WM_DELETE_WINDOW.");
|
|
|
|
xcb_intern_atom_cookie_t c_minimize = xcb_intern_atom(window->connection, 0, 20, "_NET_WM_STATE_HIDDEN");
|
|
xcb_intern_atom_reply_t *r_minimize = xcb_intern_atom_reply(window->connection, c_minimize, &error);
|
|
XCB_CHECK_CURRENT_ERROR(window, error, "Failed to get _NET_WM_STATE_HIDDEN");
|
|
|
|
cookie = xcb_change_property_checked(
|
|
window->connection,
|
|
XCB_PROP_MODE_REPLACE,
|
|
window->window,
|
|
r_proto->atom,
|
|
XCB_ATOM_ATOM,
|
|
32,
|
|
1,
|
|
&r_close->atom
|
|
);
|
|
XCB_CHECK_ERROR(window, cookie, error, "Failed to set window close event.");
|
|
|
|
window->close_event = r_close->atom;
|
|
window->minimize_event = r_minimize->atom;
|
|
|
|
free(r_proto);
|
|
free(r_close);
|
|
free(r_minimize);
|
|
|
|
xcb_map_window(window->connection, window->window);
|
|
|
|
i32 stream_result = xcb_flush(window->connection);
|
|
if (stream_result <= 0)
|
|
{
|
|
Printfln("Error flushing the stream: %d", stream_result);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
Window *_GetWindow() {
|
|
return &linux_window;
|
|
}
|
|
|
|
WindowSize _GetWindowSize()
|
|
{
|
|
return (WindowSize) {
|
|
.w = linux_window.w,
|
|
.h = linux_window.h,
|
|
};
|
|
}
|
|
|
|
b32 _GetWindowEvent(WindowEvent *event)
|
|
{
|
|
return HandleWindowEvent(event, false);
|
|
}
|
|
|
|
void _WaitForWindowEvent(WindowEvent *event)
|
|
{
|
|
HandleWindowEvent(event, true);
|
|
}
|
|
|
|
b32 HandleWindowEvent(WindowEvent *event, b32 wait_for_event)
|
|
{
|
|
Assert(event != NULL, "GetWindowEvent received a null pointer");
|
|
|
|
b32 valid_event = false;
|
|
b32 no_event = false;
|
|
do
|
|
{
|
|
xcb_generic_event_t *e;
|
|
if (wait_for_event)
|
|
e = xcb_wait_for_event(linux_window.connection);
|
|
else
|
|
e = xcb_poll_for_event(linux_window.connection);
|
|
|
|
// XCB_UNMAP_NOTIFY
|
|
if (e != NULL)
|
|
{
|
|
switch (e->response_type & ~0x80)
|
|
{
|
|
case XCB_CLIENT_MESSAGE:
|
|
xcb_client_message_event_t *msg = (xcb_client_message_event_t *)e;
|
|
if (msg->data.data32[0] == linux_window.close_event)
|
|
{
|
|
event->type = EVENT_QUIT;
|
|
valid_event = true;
|
|
}
|
|
if (msg->data.data32[0] == linux_window.minimize_event)
|
|
{
|
|
event->type = EVENT_MINIMIZE;
|
|
valid_event = true;
|
|
linux_window.w = 0;
|
|
linux_window.h = 0;
|
|
}
|
|
break;
|
|
case XCB_UNMAP_NOTIFY:
|
|
break;
|
|
case XCB_EXPOSE:
|
|
event->type = EVENT_SHOW;
|
|
|
|
xcb_expose_event_t *expose_e = (xcb_expose_event_t *)e;
|
|
linux_window.w = expose_e->width;
|
|
linux_window.h = expose_e->height;
|
|
break;
|
|
case XCB_CONFIGURE_NOTIFY:
|
|
xcb_configure_notify_event_t *configure_event = (xcb_configure_notify_event_t *)e;
|
|
|
|
if (linux_window.w != configure_event->width || linux_window.h != configure_event->height)
|
|
{
|
|
event->type = EVENT_RESIZE;
|
|
valid_event = true;
|
|
|
|
event->resize.w = configure_event->width;
|
|
event->resize.h = configure_event->height;
|
|
|
|
linux_window.w = configure_event->width;
|
|
linux_window.h = configure_event->height;
|
|
}
|
|
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
free(e);
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
|
|
|
|
} while(!valid_event && !wait_for_event);
|
|
|
|
return valid_event;
|
|
}
|
|
|
|
b32 ChangeWorkingDir(const char *)
|
|
{
|
|
b32 success = false;
|
|
|
|
return success;
|
|
}
|
|
|
|
u8 *OpenFile(const char *)
|
|
{
|
|
u8 *bytes = NULL;
|
|
|
|
return bytes;
|
|
}
|