Fumofumotris/source/io/platforms/win.c

210 lines
4.1 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-04-24 23:37:47 +00:00
#include "parseinput.h"
2024-04-29 20:01:48 +00:00
#include "ringbuffer.h"
2024-04-24 23:37:47 +00:00
#define MOUSE_MOVE (MOUSE_EVENT | MOUSE_MOVED)
#define MOUSE_VWHEEL (MOUSE_EVENT | MOUSE_WHEELED)
#define MOUSE_HWHEEL (MOUSE_EVENT | MOUSE_HWHEELED)
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-24 23:37:47 +00:00
struct win_coord {
SHORT x;
SHORT y;
};
struct win_key {
BOOL is_down;
WORD repeat;
WORD vk_code;
WORD vs_code;
WCHAR ucs2_char;
DWORD state;
};
struct win_mouse {
struct win_coord pos;
DWORD but;
DWORD state;
union {
DWORD flags;
struct {
DWORD is_moved : 1;
DWORD is_dbl_clk : 1;
DWORD is_vwheel : 1;
DWORD is_hwheel : 1;
};
struct {
DWORD : 2;
DWORD wheel : 2;
};
};
};
2024-04-24 23:37:47 +00:00
struct win_rec {
union {
WORD type;
struct {
WORD is_key : 1;
WORD is_mouse : 1;
WORD is_window : 1;
WORD is_menu : 1;
WORD is_focus : 1;
};
};
union {
struct win_key key;
struct win_mouse mouse;
2024-04-24 23:37:47 +00:00
struct win_coord window;
};
};
2024-04-29 20:01:48 +00:00
union record {
struct win_rec native;
INPUT_RECORD win;
};
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-30 06:04:25 +00:00
bool dispatch_rec(
struct InputRecord *out,
struct InputStringBuf *str,
struct win_rec *rec
) {
u8f type = rec->type | (rec->is_mouse & rec->mouse.flags);
switch (type) {
2024-04-30 06:04:25 +00:00
case KEY_EVENT: {
ReadButton(out, rec->key.vk_code, rec->key.is_down);
2024-04-29 20:01:48 +00:00
2024-04-30 06:04:25 +00:00
if (rec->key.is_down)
str->head.len += UCS2ToUTF8(str->buf, rec->key.ucs2_char);
2024-04-29 20:01:48 +00:00
2024-04-30 06:04:25 +00:00
return true;
}
case MOUSE_MOVE: {
ReadJoystick(out, 0, rec->mouse.pos.x, rec->mouse.pos.y);
2024-04-29 20:01:48 +00:00
2024-04-30 06:04:25 +00:00
return true;
}
case MOUSE_VWHEEL: {
ReadAxis(out, 0, rec->mouse.but);
2024-04-29 20:01:48 +00:00
2024-04-30 06:04:25 +00:00
return true;
}
case MOUSE_HWHEEL: {
ReadAxis(out, 1, rec->mouse.but);
return true;
}
case WINDOW_BUFFER_SIZE_EVENT: {
// TODO: Handle window resizing
return false;
}
2024-04-11 19:57:22 +00:00
}
return false;
}
2024-04-30 06:04:25 +00:00
bool PlatformReadInput(struct InputRecordBuf *recs, struct InputStringBuf *str)
2024-04-11 19:57:22 +00:00
{
2024-04-29 20:01:48 +00:00
DWORD read_max = RingBufferEmpty(&IO_BUF_T, &recs->head);
union record win_buf[read_max];
2024-04-18 05:04:44 +00:00
DWORD filled;
2024-04-22 22:13:13 +00:00
2024-04-29 20:01:48 +00:00
if (!ReadConsoleInputW(win.input_hand, &win_buf->win, read_max, &filled))
2024-04-11 19:57:22 +00:00
return false;
Time now = TimeNow();
2024-04-18 05:04:44 +00:00
for (size_t i = 0; i < filled; i++) {
2024-04-29 20:01:48 +00:00
struct InputRecord *rec = RingBufferNext(&IO_BUF_T, &recs->head);
2024-04-30 06:04:25 +00:00
if (dispatch_rec(rec, str, &win_buf->native + i)) {
rec->time = now;
2024-04-29 20:01:48 +00:00
recs->head.len += 1;
}
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
}