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-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;
|
|
|
|
};
|
|
|
|
|
2024-04-25 07:04:43 +00:00
|
|
|
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 {
|
2024-04-25 07:04:43 +00:00
|
|
|
struct win_key key;
|
|
|
|
struct win_mouse mouse;
|
2024-04-24 23:37:47 +00:00
|
|
|
struct win_coord window;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
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(
|
2024-05-02 22:17:37 +00:00
|
|
|
struct InputRecord *rec,
|
|
|
|
struct StringBuffer *str,
|
|
|
|
struct win_rec *win
|
2024-04-30 06:04:25 +00:00
|
|
|
) {
|
2024-05-02 22:17:37 +00:00
|
|
|
u8f type = win->type | (win->is_mouse & win->mouse.flags);
|
2024-04-25 07:04:43 +00:00
|
|
|
|
|
|
|
switch (type) {
|
2024-04-30 06:04:25 +00:00
|
|
|
case KEY_EVENT: {
|
2024-05-02 22:17:37 +00:00
|
|
|
ReadButton(rec, win->key.vk_code, win->key.is_down);
|
2024-04-29 20:01:48 +00:00
|
|
|
|
2024-05-02 22:17:37 +00:00
|
|
|
if (win->key.is_down)
|
|
|
|
str->head.len += UCS2ToUTF8(str->buf, win->key.ucs2_char);
|
2024-04-29 20:01:48 +00:00
|
|
|
|
2024-04-30 06:04:25 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case MOUSE_MOVE: {
|
2024-05-02 22:17:37 +00:00
|
|
|
ReadJoystick(rec, 0, win->mouse.pos.x, win->mouse.pos.y);
|
2024-04-29 20:01:48 +00:00
|
|
|
|
2024-04-30 06:04:25 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case MOUSE_VWHEEL: {
|
2024-05-02 22:17:37 +00:00
|
|
|
ReadAxis(rec, 0, win->mouse.but);
|
2024-04-29 20:01:48 +00:00
|
|
|
|
2024-04-30 06:04:25 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case MOUSE_HWHEEL: {
|
2024-05-02 22:17:37 +00:00
|
|
|
ReadAxis(rec, 1, win->mouse.but);
|
2024-04-30 06:04:25 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case WINDOW_BUFFER_SIZE_EVENT: {
|
|
|
|
// TODO: Handle window resizing
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2024-04-11 19:57:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-05-02 22:17:37 +00:00
|
|
|
size_t read_input(struct win_rec *buf, size_t n)
|
2024-04-11 19:57:22 +00:00
|
|
|
{
|
2024-05-02 22:17:37 +00:00
|
|
|
DWORD len;
|
2024-05-06 05:52:30 +00:00
|
|
|
if (!ReadConsoleInputW(win.input_hand, (INPUT_RECORD *)buf, n, &len))
|
2024-05-02 22:17:37 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
return len;
|
|
|
|
}
|
2024-04-22 22:13:13 +00:00
|
|
|
|
2024-05-02 22:17:37 +00:00
|
|
|
bool PlatformReadInput(struct RecordBuffer *recs, struct StringBuffer *str)
|
|
|
|
{
|
|
|
|
size_t n = RingBufferEmpty(IO_BUF_T, &recs->head);
|
|
|
|
struct win_rec buf[n];
|
|
|
|
|
|
|
|
size_t len = read_input(buf, n);
|
|
|
|
if (len == 0)
|
2024-04-11 19:57:22 +00:00
|
|
|
return false;
|
|
|
|
|
2024-05-07 03:29:10 +00:00
|
|
|
nsec now = TimeNow();
|
2024-04-25 07:04:43 +00:00
|
|
|
|
2024-05-02 22:17:37 +00:00
|
|
|
for (size_t i = 0; i < len; i++) {
|
|
|
|
struct InputRecord *rec = RingBufferNext(IO_BUF_T, &recs->head);
|
2024-04-25 07:04:43 +00:00
|
|
|
|
2024-05-02 22:17:37 +00:00
|
|
|
if (dispatch_rec(rec, str, &buf[i])) {
|
2024-04-25 07:04:43 +00:00
|
|
|
rec->time = now;
|
2024-04-29 20:01:48 +00:00
|
|
|
recs->head.len += 1;
|
2024-04-25 07:04:43 +00:00
|
|
|
}
|
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-05-07 03:29:10 +00:00
|
|
|
bool PlatformWait(nsec 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
|
|
|
}
|