diff options
| author | dam <devnull@localhost> | 2024-02-16 02:33:20 +0000 |
|---|---|---|
| committer | dam <devnull@localhost> | 2024-02-16 02:33:20 +0000 |
| commit | cbb4b1f06b2395705851430742e23240ece90510 (patch) | |
| tree | b8ca6b4a657db467768147fe1c32ce07c85a1bc3 /TUI/windows.jai | |
| parent | b3c9a89d19a3021f56a8d9249307a0c38ee5cfd6 (diff) | |
| download | task-time-tracker-cbb4b1f06b2395705851430742e23240ece90510.tar.zst task-time-tracker-cbb4b1f06b2395705851430742e23240ece90510.zip | |
Base implementation of TUI/windows.
Diffstat (limited to 'TUI/windows.jai')
| -rw-r--r-- | TUI/windows.jai | 116 |
1 files changed, 70 insertions, 46 deletions
diff --git a/TUI/windows.jai b/TUI/windows.jai index ff4d6a1..f79a5cf 100644 --- a/TUI/windows.jai +++ b/TUI/windows.jai @@ -15,6 +15,7 @@ WORD :: u16; DWORD :: s32; LPDWORD :: *s32; + UINT :: u32; PINPUT_RECORD :: *INPUT_RECORD; @@ -107,6 +108,14 @@ dwMaximumWindowSize : COORD; } + INPUT_RECORD_EVENT_TYPE :: enum u16 { + KEY_EVENT :: 0x0001; + MOUSE_EVENT :: 0x0002; + WINDOW_BUFFER_SIZE_EVENT :: 0x0004; + MENU_EVENT :: 0x0008; + FOCUS_EVENT :: 0x0010; + } + INPUT_RECORD :: struct { EventType : INPUT_RECORD_EVENT_TYPE; union { @@ -114,23 +123,14 @@ MouseEvent : MOUSE_EVENT_RECORD; WindowBufferSizeEvent : WINDOW_BUFFER_SIZE_RECORD; // These events are used internally and should be ignored. - //MenuEvent : MENU_EVENT_RECORD; - //FocusEvent : FOCUS_EVENT_RECORD; + MenuEvent : MENU_EVENT_RECORD; + FocusEvent : FOCUS_EVENT_RECORD; } - //Event : EventUnion; } - INPUT_RECORD_EVENT_TYPE :: enum s32 { - KEY_EVENT :: 0x0001; - MOUSE_EVENT :: 0x0002; - WINDOW_BUFFER_SIZE_EVENT :: 0x0004; - MENU_EVENT :: 0x0008; - FOCUS_EVENT :: 0x0010; - } - KEY_EVENT_RECORD :: struct { bKeyDown : BOOL; - wRepeatCount : WORD; + wRepeatCount : WORD #align 4; wVirtualKeyCode : WORD; wVirtualScanCode : WORD; union { @@ -151,6 +151,14 @@ dwSize : COORD; } + MENU_EVENT_RECORD :: struct { + dwCommandId : UINT; + } + + FOCUS_EVENT_RECORD :: struct { + bSetFocus : BOOL; + } + stdin: HANDLE; initial_stdin_mode: u32; raw_stdin_mode: Console_Input_Mode; @@ -297,13 +305,23 @@ OS_read_input :: (buffer: *u8, bytes_to_read: s64) -> bytes_read: s64, error: bo assert(bytes_to_read <= 0x7fff_ffff, "The Windows API only allows to read up to s32 bytes from the standard input."); - bytes_read: s32; - success := ReadConsoleA(stdin, buffer, cast(s32)bytes_to_read, *bytes_read); - if success == false { - _, error_message := get_error_value_and_string(); - return -1, true, error_message; + bytes_read: s32 = 0; + available_inputs := count_input(); + + while bytes_to_read > 0 && available_inputs > 0 { + record := read_input(); + + if record.EventType == .WINDOW_BUFFER_SIZE_EVENT { + was_resized = true; + } + + if record.EventType == .KEY_EVENT && record.KeyEvent.bKeyDown == true { + buffer[bytes_read] = xx record.KeyEvent.AsciiChar; + bytes_to_read -= 1; + bytes_read += 1; + } + available_inputs -= 1; } - // print(">%:%<", bytes_to_read, bytes_read); TODO DEBUG return bytes_read; } @@ -311,23 +329,22 @@ OS_read_input :: (buffer: *u8, bytes_to_read: s64) -> bytes_read: s64, error: bo // 0: do not wait // -1: wait indefinitely OS_wait_for_input :: (timeout_milliseconds: s32 = -1) -> is_input_available: bool { - /* TODO - Try to implement using: - https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitforsingleobjectex - This wait procedure on windows should check if next input is valid (keyboard down) before returning, otherwise it should discar that input and go back to wait (if more sleep is allowed). + /* TODO + Add a good comment explaining how the windows part of the module was implemented... what's the idea behind it. + Something like, Since windows provides a single input buffer with all events, we need to peek through them and + discard the ones that are of no use for us. + Because it's a single buffer, all functions need to do repeated work (see if it's resize, see if it's a key press) + ... and so on. */ - + expiration := current_time_monotonic() + to_apollo(timeout_milliseconds / 1000.0); - // Possible values for poll_return TODO NOT BEING USED - WAIT_ABANDONED :: 0x00000080; - //WAIT_IO_COMPLETION :: 0x000000C0; - WAIT_OBJECT_0 :: 0x00000000; - WAIT_TIMEOUT :: 0x00000102; - WAIT_FAILED :: 0xFFFFFFFF; - //return ifx poll_return == WAIT_OBJECT_0 then true else false; + WAIT_ABANDONED :: 0x00000080; // Mutex stuff. + WAIT_OBJECT_0 :: 0x00000000; // Detected input. + WAIT_TIMEOUT :: 0x00000102; // Reached timeout. + WAIT_FAILED :: 0xFFFFFFFF; // Something went wrong. while true { poll_return := WaitForSingleObject(stdin, timeout_milliseconds); @@ -343,19 +360,33 @@ OS_wait_for_input :: (timeout_milliseconds: s32 = -1) -> is_input_available: boo _, error_message := get_error_value_and_string(); assert(false, error_message); } -// if poll_return != WAIT_OBJECT_0 then return false; - // Discard invalid input until a valid input is found or no input is left. + // Discard invalid input events. count := count_input(); while count > 0 { record := peek_input(); - if record.EventType == .KEY_EVENT && record.KeyEvent.bKeyDown == true || record.EventType == .WINDOW_BUFFER_SIZE_EVENT { + + if record.EventType == .WINDOW_BUFFER_SIZE_EVENT { + // Discard any additional resize event. + while peek_input().EventType == .WINDOW_BUFFER_SIZE_EVENT { + was_resized = true; + read_input(); + } + return false; + } + + if record.EventType == .KEY_EVENT && record.KeyEvent.bKeyDown == true { return true; } - read_input(); // TODO Discard input. + + read_input(); count -= 1; } - + + // When waiting indefinitely... just continue. + if timeout_milliseconds < 0 then continue; + + // Either break due to timeout, or update the remaining timeout. now := current_time_monotonic(); if now >= expiration then return false; timeout_milliseconds = xx to_milliseconds(expiration - now); @@ -365,18 +396,11 @@ OS_wait_for_input :: (timeout_milliseconds: s32 = -1) -> is_input_available: boo } OS_was_terminal_resized :: () -> bool { - - defer was_resized = false; // TODO Not using this flag... what happens if ... not sure what... :thinking: - - flag: = false; - - record := peek_input(); - while record.EventType == .WINDOW_BUFFER_SIZE_EVENT { + while peek_input().EventType == .WINDOW_BUFFER_SIZE_EVENT { + was_resized = true; read_input(); - record = peek_input(); - flag = true; } - //return was_resized; - return flag; + defer was_resized = false; + return was_resized; } |
