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 {
|
2024-04-22 22:13:13 +00:00
|
|
|
HANDLE input_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;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-04-15 19:29:51 +00:00
|
|
|
bool init_console()
|
2024-04-11 19:57:22 +00:00
|
|
|
{
|
2024-04-23 20:33:32 +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-23 20:33:32 +00:00
|
|
|
inline size_t ucs2_to_utf8(u16f ucs2, size_t n, char *buf) {
|
|
|
|
return WideCharToMultiByte(CP_UTF8, 0, ucs2, 1, buf, n, NULL, NULL);
|
2024-03-25 05:34:59 +00:00
|
|
|
}
|
|
|
|
|
2024-04-23 20:33:32 +00:00
|
|
|
void read_key(
|
|
|
|
struct InputBuffer *in,
|
|
|
|
struct InputString *str,
|
|
|
|
KEY_EVENT_RECORD *key
|
|
|
|
) {
|
|
|
|
struct InputRecord *rec = &in->buf[in->len++];
|
2024-04-11 19:57:22 +00:00
|
|
|
|
2024-04-23 20:33:32 +00:00
|
|
|
rec->id.type = BUTTON;
|
|
|
|
rec->id.bind = key->wVirtualKeyCode;
|
2024-04-11 19:57:22 +00:00
|
|
|
|
2024-04-23 20:33:32 +00:00
|
|
|
rec->is_down = key->bKeyDown;
|
|
|
|
rec->is_up = !key->bKeyDown;
|
2024-04-03 23:31:47 +00:00
|
|
|
|
2024-04-23 20:33:32 +00:00
|
|
|
ucs2_to_utf8(key->uChar.UnicodeChar, IO_BUF_SIZE - str->len, str->buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool is_mouse_wheel(DWORD event_flags) {
|
|
|
|
return (event_flags & (MOUSE_WHEELED | MOUSE_HWHEELED)) != 0;
|
2024-04-11 19:57:22 +00:00
|
|
|
}
|
|
|
|
|
2024-04-23 20:33:32 +00:00
|
|
|
void read_mouse(struct InputBuffer *in, MOUSE_EVENT_RECORD *mouse)
|
2024-04-11 19:57:22 +00:00
|
|
|
{
|
2024-04-23 20:33:32 +00:00
|
|
|
if (mouse->dwEventFlags == MOUSE_MOVED) {
|
|
|
|
struct InputRecord *rec = &in->buf[in->len++];
|
|
|
|
|
|
|
|
rec->id.type = JOYSTICK;
|
|
|
|
rec->id.bind = 0;
|
|
|
|
rec->js.x = mouse->dwMousePosition.X;
|
|
|
|
rec->js.y = mouse->dwMousePosition.Y;
|
|
|
|
} else if (is_mouse_wheel(mouse->dwEventFlags)) {
|
|
|
|
struct InputRecord *rec = &in->buf[in->len++];
|
|
|
|
|
|
|
|
rec->id.type = AXIS;
|
|
|
|
rec->id.bind = (mouse->dwEventFlags == MOUSE_WHEELED);
|
|
|
|
rec->axis.value = mouse->dwButtonState;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool read_rec(
|
|
|
|
struct InputBuffer *in,
|
|
|
|
struct InputString *str,
|
|
|
|
INPUT_RECORD *rec
|
|
|
|
) {
|
|
|
|
switch (rec->EventType) {
|
2024-04-11 19:57:22 +00:00
|
|
|
case KEY_EVENT:
|
2024-04-23 20:33:32 +00:00
|
|
|
read_key(in, str, &rec->Event.KeyEvent);
|
2024-04-11 19:57:22 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
case MOUSE_EVENT:
|
2024-04-23 20:33:32 +00:00
|
|
|
read_mouse(in, &rec->Event.MouseEvent);
|
|
|
|
return true;
|
2024-04-11 19:57:22 +00:00
|
|
|
|
|
|
|
case WINDOW_BUFFER_SIZE_EVENT:
|
2024-04-23 20:33:32 +00:00
|
|
|
return true;
|
2024-04-11 19:57:22 +00:00
|
|
|
// TODO: Handle window resizing
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-04-23 20:33:32 +00:00
|
|
|
bool PlatformReadInput(struct InputBuffer *in, struct InputString *str)
|
2024-04-11 19:57:22 +00:00
|
|
|
{
|
2024-04-23 20:33:32 +00:00
|
|
|
DWORD max_records = IO_BUF_SIZE - in->len;
|
2024-04-18 05:04:44 +00:00
|
|
|
INPUT_RECORD win_buf[max_records];
|
|
|
|
DWORD filled;
|
2024-04-22 22:13:13 +00:00
|
|
|
|
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-18 05:04:44 +00:00
|
|
|
for (size_t i = 0; i < filled; i++) {
|
2024-04-23 20:33:32 +00:00
|
|
|
if (!read_rec(in, str, win_buf + i))
|
|
|
|
return false;
|
2024-04-11 19:57:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-04-19 20:23:11 +00:00
|
|
|
bool PlatformStopInput()
|
|
|
|
{
|
2024-04-22 22:13:13 +00:00
|
|
|
return CancelSynchronousIo(win.input_hand);
|
2024-04-19 20:23:11 +00:00
|
|
|
}
|
|
|
|
|
2024-04-22 22:13:13 +00:00
|
|
|
bool PlatformWait(Time duration)
|
2024-04-11 19:57:22 +00:00
|
|
|
{
|
2024-04-22 22:13:13 +00:00
|
|
|
LARGE_INTEGER nsec_div_100;
|
|
|
|
nsec_div_100.QuadPart = -duration / 100;
|
2024-04-11 19:57:22 +00:00
|
|
|
|
2024-04-22 22:13:13 +00:00
|
|
|
if (!SetWaitableTimer(win.timer, &nsec_div_100, 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
|
|
|
}
|