Fumofumotris/source/io/platforms/win.c

165 lines
3.6 KiB
C
Raw Normal View History

2024-04-19 06:38:45 +00:00
#include "win.h"
2024-04-11 19:57:22 +00:00
#include <windows.h>
2024-03-25 05:34:59 +00:00
2024-04-16 22:14:53 +00:00
#include "gametime.h"
2024-04-19 06:38:45 +00:00
#include "input.h"
2024-03-25 05:34:59 +00:00
2024-04-19 20:23:11 +00:00
struct windows {
union {
HANDLE input_hands[2];
struct {
HANDLE input_hand;
HANDLE early_exit_hand;
};
};
2024-04-11 19:57:22 +00:00
HANDLE timer;
2024-04-15 19:29:51 +00:00
} win;
2024-04-11 19:57:22 +00:00
2024-04-15 19:29:51 +00:00
bool init_handles()
2024-03-25 05:34:59 +00:00
{
2024-04-19 20:23:11 +00:00
win.input_hand = GetStdHandle(STD_INPUT_HANDLE);
if (win.input_hand == INVALID_HANDLE_VALUE)
2024-03-25 05:34:59 +00:00
return false;
2024-04-18 05:04:44 +00:00
win.timer = CreateWaitableTimerW(NULL, TRUE, NULL);
2024-04-15 19:29:51 +00:00
if (win.timer == NULL)
2024-04-11 19:57:22 +00:00
return false;
2024-04-19 20:23:11 +00:00
win.early_exit_hand = CreateEventW(NULL, FALSE, FALSE, NULL);
if (win.early_exit_hand == NULL)
return false;
2024-04-11 19:57:22 +00:00
return true;
}
2024-04-15 19:29:51 +00:00
bool init_console()
2024-04-11 19:57:22 +00:00
{
DWORD mode = ENABLE_EXTENDED_FLAGS
| ENABLE_PROCESSED_INPUT
| ENABLE_PROCESSED_OUTPUT
| ENABLE_MOUSE_INPUT
| ENABLE_WINDOW_INPUT;
2024-04-18 05:04:44 +00:00
2024-04-19 20:23:11 +00:00
return SetConsoleMode(win.input_hand, mode) != 0;
2024-04-15 19:29:51 +00:00
}
bool PlatformInit()
{
if (!init_handles())
return false;
if (!init_console())
return false;
return true;
2024-04-11 19:57:22 +00:00
}
2024-04-15 19:29:51 +00:00
bool PlatformGetRefreshRate(u16f *out)
2024-04-11 19:57:22 +00:00
{
2024-04-19 20:23:11 +00:00
DEVMODEW mode;
mode.dmSize = sizeof(DEVMODEW);
2024-04-11 19:57:22 +00:00
mode.dmDriverExtra = 0;
2024-04-19 20:23:11 +00:00
if(!EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &mode))
2024-04-11 19:57:22 +00:00
return false;
*out = mode.dmDisplayFrequency;
return true;
}
2024-04-18 05:04:44 +00:00
void copy_key_event(struct InputRecord *rec, KEY_EVENT_RECORD *win_key)
2024-03-25 05:34:59 +00:00
{
2024-04-11 19:57:22 +00:00
rec->type = BUTTON;
2024-04-18 05:04:44 +00:00
rec->bind = win_key->wVirtualKeyCode;
2024-04-11 19:57:22 +00:00
2024-04-18 05:04:44 +00:00
rec->is_down = win_key->bKeyDown;
rec->is_up = !win_key->bKeyDown;
2024-03-25 05:34:59 +00:00
}
2024-04-18 05:04:44 +00:00
bool copy_mouse_event(struct InputRecord *rec, MOUSE_EVENT_RECORD *win_mouse)
2024-03-25 05:34:59 +00:00
{
2024-04-18 05:04:44 +00:00
if (win_mouse->dwEventFlags == MOUSE_MOVED) {
2024-04-11 19:57:22 +00:00
rec->type = JOYSTICK;
rec->bind = 0;
2024-04-18 05:04:44 +00:00
rec->js.x = win_mouse->dwMousePosition.X;
rec->js.y = win_mouse->dwMousePosition.Y;
2024-04-11 19:57:22 +00:00
return true;
}
2024-04-22 05:19:54 +00:00
if ((win_mouse->dwEventFlags & (MOUSE_WHEELED | MOUSE_HWHEELED)) != 0) {
2024-04-18 05:04:44 +00:00
rec->type = AXIS;
rec->bind = win_mouse->dwEventFlags == MOUSE_WHEELED;
rec->axis.value = win_mouse->dwButtonState;
2024-04-11 19:57:22 +00:00
2024-04-18 05:04:44 +00:00
return true;
}
2024-04-03 23:31:47 +00:00
2024-04-18 05:04:44 +00:00
return false;
2024-04-11 19:57:22 +00:00
}
2024-04-18 05:04:44 +00:00
bool copy_rec(struct InputRecord *rec, INPUT_RECORD *win_rec)
2024-04-11 19:57:22 +00:00
{
2024-04-18 05:04:44 +00:00
switch (win_rec->EventType) {
2024-04-11 19:57:22 +00:00
case KEY_EVENT:
2024-04-18 05:04:44 +00:00
copy_key_event(rec, &win_rec->Event.KeyEvent);
2024-04-11 19:57:22 +00:00
return true;
case MOUSE_EVENT:
2024-04-18 05:04:44 +00:00
return copy_mouse_event(rec, &win_rec->Event.MouseEvent);
2024-04-11 19:57:22 +00:00
case WINDOW_BUFFER_SIZE_EVENT:
return false;
// TODO: Handle window resizing
}
rec->type = ESCAPE;
return false;
}
2024-04-18 05:04:44 +00:00
bool PlatformReadInput(struct InputBuffer *buf)
2024-04-11 19:57:22 +00:00
{
2024-04-19 20:23:11 +00:00
DWORD wait_status = WaitForMultipleObjects(2, win.input_hands, FALSE, 0);
if (wait_status != 0)
return wait_status == 1;
2024-04-18 05:04:44 +00:00
DWORD max_records = IO_BUF_SIZE - buf->len;
INPUT_RECORD win_buf[max_records];
DWORD filled;
2024-04-19 20:23:11 +00:00
if (!ReadConsoleInputW(win.input_hand, win_buf, max_records, &filled))
2024-04-11 19:57:22 +00:00
return false;
2024-04-19 06:38:45 +00:00
struct InputRecord rec = { .time = TimeNow() };
2024-04-11 19:57:22 +00:00
2024-04-18 05:04:44 +00:00
for (size_t i = 0; i < filled; i++) {
if (!copy_rec(&rec, win_buf + i))
2024-04-11 19:57:22 +00:00
continue;
2024-04-19 06:38:45 +00:00
InputBufferAdd(buf, &rec);
2024-04-11 19:57:22 +00:00
}
return true;
}
2024-04-19 20:23:11 +00:00
bool PlatformStopInput()
{
return SetEvent(win.early_exit_hand) == 0;
}
2024-04-19 06:38:45 +00:00
bool PlatformWait(struct Time relative)
2024-04-11 19:57:22 +00:00
{
LARGE_INTEGER duration;
2024-04-19 06:38:45 +00:00
duration.QuadPart = -10000000 * relative.sec - relative.nsec / 100;
2024-04-11 19:57:22 +00:00
2024-04-19 20:23:11 +00:00
if (!SetWaitableTimer(win.timer, &duration, 0, NULL, NULL, FALSE))
2024-04-11 19:57:22 +00:00
return false;
2024-04-15 19:29:51 +00:00
DWORD result = WaitForSingleObject(win.timer, INFINITE);
2024-04-11 19:57:22 +00:00
if (result != WAIT_OBJECT_0)
return false;
return true;
2024-03-25 05:34:59 +00:00
}