diff --git a/examples/cursor-position-query.cpp b/examples/cursor-position-query.cpp new file mode 100644 index 0000000..39781bd --- /dev/null +++ b/examples/cursor-position-query.cpp @@ -0,0 +1,34 @@ +#include "../tui.hpp" +#include +#include +#include +// #include + +// returns how much the queries altogether took in ns +uint64_t get_cursor_pos_n(const unsigned n) { + auto start = std::chrono::high_resolution_clock::now(); + for (auto i = 0; i < n; ++i) { + // std::cout << "getting cursor position...\n"; + auto cursor_pos = tui::cursor::get_position(); + // std::cout << "cursor @ {" << cursor_pos.first << ", " << cursor_pos.second << "}\n"; + // assert(cursor_pos == cursor_pos_tty); + // std::this_thread::sleep_for(std::chrono::milliseconds(800)); + } + auto end = std::chrono::high_resolution_clock::now(); + return std::chrono::duration_cast(end - start).count(); +} + +int main(int argc, char** argv) { + tui::enable_raw_mode(); + + unsigned n = 8; + if (argc > 1) { + n = std::stoi(argv[1]); + } + + auto query_t_sum = get_cursor_pos_n(n); + // std::this_thread::sleep_for(std::chrono::seconds(8)); + tui::disable_raw_mode(); + std::cout << "getting cursor " << n << " times took: " << query_t_sum / 1000000 << "ms, avg: " << query_t_sum / n <<"ns\n"; + return 0; +} diff --git a/tui.hpp b/tui.hpp index 8cb432b..7904707 100644 --- a/tui.hpp +++ b/tui.hpp @@ -3,7 +3,6 @@ #ifdef _WIN32 // windows -#include #include #else // not windows @@ -20,7 +19,6 @@ #include #include #include -#include #include #include #include // for std::pair @@ -60,7 +58,7 @@ namespace tui { exit(1); \ } \ DWORD mode; \ - if (!GetConsoleMode(hStdin, &mode)) { \ + if (GetConsoleMode(hStdin, &mode) == 0) { \ std::cerr << "error getting the console mode\n"; \ exit(1); \ } @@ -73,7 +71,7 @@ namespace tui { DWORD newMode = mode; newMode &= ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT); - if (!SetConsoleMode(hStdin, newMode)) { + if (SetConsoleMode(hStdin, newMode) == 0) { std::cerr << "error setting the console to raw mode\n"; exit(1); } @@ -102,7 +100,7 @@ namespace tui { // Restore original mode mode |= (ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT); - if (!SetConsoleMode(hStdin, mode)) { + if (SetConsoleMode(hStdin, mode) == 0) { std::cerr << "error restoring the console mode\n"; exit(1); } @@ -124,6 +122,27 @@ namespace tui { #undef win_setup +#ifdef _WIN32 + inline CONSOLE_SCREEN_BUFFER_INFO get_console_buf_info() { + HANDLE console = nullptr; + CONSOLE_SCREEN_BUFFER_INFO info; + // create a handle to the console screen + console = CreateFileW(L"CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, + OPEN_EXISTING, 0, nullptr); + if (console == INVALID_HANDLE_VALUE) { + std::cerr << "couldn't get console handle\n"; + exit(1); + } + // calculate the size of the console window + if (GetConsoleScreenBufferInfo(console, &info) == 0) { + std::cerr << "couldn't get console screen buffer info\n"; + exit(1); + } + CloseHandle(console); + return info; + } +#endif + namespace cursor { // template for moving cursor // moves cursor `n` times to `dir` @@ -161,8 +180,17 @@ namespace tui { // tell the terminal to check where the cursor is csi_fn(query_position, "6n"); +#ifdef _WIN32 + // returns: (rows;cols) + inline std::pair get_position() { + auto info = get_console_buf_info(); + auto rows = info.dwCursorPosition.X + 1; + auto cols = info.dwCursorPosition.Y + 1; + return {rows, cols}; + } +#else // returns: (rows;cols) - // WARN: can be quite slow, don't use on eg. every screen update! + // NOTE: can take a while (eg 16ms) on (relatively) slow terminals inline std::pair get_position() { query_position(); std::flush(std::cout); @@ -179,6 +207,8 @@ namespace tui { return {rows, cols}; } +#endif + } // namespace cursor namespace screen { @@ -204,22 +234,9 @@ namespace tui { // returns: (rows;cols)/(y;x) inline std::pair size() { #ifdef _WIN32 - HANDLE console; - CONSOLE_SCREEN_BUFFER_INFO info; - short rows; - short columns; - // create a handle to the console screen - console = CreateFileW(L"CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, - OPEN_EXISTING, 0, NULL); - if (console == INVALID_HANDLE_VALUE) - return {0, 0}; - - // calculate the size of the console window - if (GetConsoleScreenBufferInfo(console, &info) == 0) - return {0, 0}; - CloseHandle(console); - columns = info.srWindow.Right - info.srWindow.Left + 1; - rows = info.srWindow.Bottom - info.srWindow.Top + 1; + auto info = get_console_buf_info(); + int columns = info.srWindow.Right - info.srWindow.Left + 1; + int rows = info.srWindow.Bottom - info.srWindow.Top + 1; return {rows, columns}; #else