Fumofumotris/source/io/platforms/winhandler.c

173 lines
4.2 KiB
C
Raw Normal View History

2024-03-25 05:34:59 +00:00
#include <iso646.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
2024-04-01 22:39:21 +00:00
#include <time.h>
2024-03-25 05:34:59 +00:00
#include "fumotris.h"
2024-03-26 20:11:58 +00:00
#include "gametime.h"
2024-03-25 05:34:59 +00:00
#include "input.h"
2024-04-03 23:31:47 +00:00
#include "term.h"
2024-03-25 05:34:59 +00:00
struct Windows {
HANDLE input_handle;
2024-04-09 07:00:48 +00:00
HANDLE timer;
2024-03-25 05:34:59 +00:00
};
2024-04-09 07:00:48 +00:00
static struct Windows win;
2024-03-25 05:34:59 +00:00
2024-04-02 20:06:14 +00:00
bool WinInitHandles()
2024-03-25 05:34:59 +00:00
{
2024-04-09 07:00:48 +00:00
win.input_handle = GetStdHandle(STD_INPUT_HANDLE);
if (win.input_handle == INVALID_HANDLE_VALUE)
2024-03-25 05:34:59 +00:00
return false;
2024-04-09 07:00:48 +00:00
win.timer = CreateWaitableTimer(
NULL, // Timer attributes
TRUE, // Manual reset
NULL // Name
2024-04-02 20:06:14 +00:00
);
2024-04-09 07:00:48 +00:00
if (!win.timer)
2024-03-25 05:34:59 +00:00
return false;
2024-04-02 20:06:14 +00:00
2024-03-25 05:34:59 +00:00
return true;
}
bool WinInitConsole()
{
DWORD mode = ENABLE_EXTENDED_FLAGS
| ENABLE_PROCESSED_INPUT
2024-04-09 22:10:30 +00:00
| ENABLE_PROCESSED_OUTPUT
2024-03-25 05:34:59 +00:00
| ENABLE_MOUSE_INPUT
2024-04-09 22:10:30 +00:00
| ENABLE_WINDOW_INPUT;
2024-04-09 07:00:48 +00:00
return SetConsoleMode(win.input_handle, mode) != 0;
2024-03-25 05:34:59 +00:00
}
2024-04-09 07:00:48 +00:00
bool WinGetRefreshRate(u16f *out)
2024-04-02 20:06:14 +00:00
{
2024-04-09 07:00:48 +00:00
DEVMODE mode;
mode.dmSize = sizeof(DEVMODE);
mode.dmDriverExtra = 0;
2024-04-02 20:06:14 +00:00
if(!EnumDisplaySettingsA(
2024-04-09 07:00:48 +00:00
NULL, // Device name (null for current)
ENUM_CURRENT_SETTINGS, // Mode
&mode // Out
2024-04-02 20:06:14 +00:00
))
return false;
2024-04-09 07:00:48 +00:00
*out = mode.dmDisplayFrequency;
2024-04-02 20:06:14 +00:00
return true;
}
2024-04-09 22:10:30 +00:00
void set_key_record(struct InputRecord *rec, KEY_EVENT_RECORD win_key)
2024-03-25 05:34:59 +00:00
{
2024-04-09 22:10:30 +00:00
rec->type = KEY;
rec->bind = win_key.wVirtualKeyCode;
rec->button.is_down = win_key.bKeyDown;
rec->button.is_up = !win_key.bKeyDown;
2024-03-25 05:34:59 +00:00
if (win_key.wVirtualKeyCode == VK_ESCAPE)
2024-04-09 22:10:30 +00:00
rec->type = ESCAPE;
2024-03-25 05:34:59 +00:00
}
2024-04-09 22:10:30 +00:00
bool set_mouse_record(struct InputRecord *rec, MOUSE_EVENT_RECORD win_mouse)
2024-03-25 05:34:59 +00:00
{
switch (win_mouse.dwEventFlags) {
case MOUSE_WHEELED:
2024-04-09 22:10:30 +00:00
rec->type = AXIS;
rec->bind = 0;
rec->axis.value = win_mouse.dwButtonState;
2024-03-25 05:34:59 +00:00
break;
case MOUSE_HWHEELED:
2024-04-09 22:10:30 +00:00
rec->type = AXIS;
rec->bind = 1;
rec->axis.value = win_mouse.dwButtonState;
2024-03-25 05:34:59 +00:00
break;
case MOUSE_MOVED:
2024-04-09 22:10:30 +00:00
rec->type = JOYSTICK;
rec->bind = 0;
rec->joystick.x = win_mouse.dwMousePosition.X;
rec->joystick.y = win_mouse.dwMousePosition.Y;
2024-03-25 05:34:59 +00:00
break;
default:
return false;
}
return true;
}
2024-04-09 22:10:30 +00:00
bool dispatch_record(struct InputRecord *rec, INPUT_RECORD win_rec)
2024-03-25 05:34:59 +00:00
{
2024-04-09 22:10:30 +00:00
switch (win_rec.EventType) {
2024-03-25 05:34:59 +00:00
case KEY_EVENT:
2024-04-09 22:10:30 +00:00
set_key_record(rec, win_rec.Event.KeyEvent);
2024-04-02 20:06:14 +00:00
break;
2024-03-25 05:34:59 +00:00
case MOUSE_EVENT:
2024-04-09 22:10:30 +00:00
return set_mouse_record(rec, win_rec.Event.MouseEvent);
2024-03-25 05:34:59 +00:00
case WINDOW_BUFFER_SIZE_EVENT:
2024-04-09 07:00:48 +00:00
// TODO: Handle window resizing
return false;
2024-03-25 05:34:59 +00:00
default:
2024-04-09 22:10:30 +00:00
rec->type = ESCAPE;
2024-03-25 05:34:59 +00:00
}
return true;
}
2024-04-02 00:55:30 +00:00
bool WinBlockInput(struct RecordBuffer *buf)
2024-03-25 05:34:59 +00:00
{
2024-03-26 20:11:58 +00:00
size_t win_size = IO_BUF_SIZE - buf->count;
INPUT_RECORD win_buf[win_size];
2024-03-25 05:34:59 +00:00
DWORD count;
2024-04-02 20:06:14 +00:00
if (!ReadConsoleInput(
2024-04-09 07:00:48 +00:00
win.input_handle, // Input handle
win_buf, // Record buffer
win_size, // Record buffer length
&count // Out number of records
2024-04-02 20:06:14 +00:00
))
2024-03-25 05:34:59 +00:00
return false;
2024-03-26 20:11:58 +00:00
2024-04-01 22:39:21 +00:00
struct timespec now;
timespec_get(&now, TIME_UTC);
2024-03-26 20:11:58 +00:00
pthread_mutex_lock(&buf->mutex);
2024-03-25 05:34:59 +00:00
for (size_t i = 0; i < count; i++) {
2024-04-09 22:10:30 +00:00
struct InputRecord rec;
rec.timestamp = now;
2024-03-25 05:34:59 +00:00
2024-04-09 22:10:30 +00:00
bool include = dispatch_record(&rec, win_buf[i]);
2024-03-25 05:34:59 +00:00
if (!include)
2024-03-26 20:11:58 +00:00
continue;
2024-03-25 05:34:59 +00:00
2024-04-09 22:10:30 +00:00
buf->records[buf->count++] = rec;
2024-03-25 05:34:59 +00:00
}
2024-03-26 20:11:58 +00:00
pthread_mutex_unlock(&buf->mutex);
2024-03-25 05:34:59 +00:00
return true;
}
2024-04-03 23:31:47 +00:00
bool WinWait(struct timespec relative)
2024-03-25 05:34:59 +00:00
{
LARGE_INTEGER duration;
2024-04-03 23:31:47 +00:00
duration.QuadPart = -10000000 * relative.tv_sec - relative.tv_nsec / 100;
2024-04-02 20:06:14 +00:00
if (!SetWaitableTimer(
2024-04-09 07:00:48 +00:00
win.timer, // Timer
2024-04-02 20:06:14 +00:00
&duration, // Duration
0, // Period
NULL, // Completion coroutine
NULL, // Completion coroutine arg
FALSE // Resume
))
2024-03-25 05:34:59 +00:00
return false;
2024-04-09 07:00:48 +00:00
DWORD result = WaitForSingleObject(win.timer, INFINITE);
2024-03-25 05:34:59 +00:00
if (result != WAIT_OBJECT_0)
return false;
return true;
}