[ Reference ]
Limitations and FAQ
Platform and terminal limitations
Section titled “Platform and terminal limitations”- POSIX-only implementation:
libkotodirectly includes<termios.h>,<poll.h>,<fcntl.h>,<sys/ioctl.h>,<unistd.h>, and<csignal>. It does not compile against the native Windows Console API without a POSIX compatibility layer such as WSL2. - Process-global signal and
termiosrecovery state:src/terminal.cpp:16-25storesg_saved,g_old_term,g_old_hup,g_old_int,g_old_quit,g_old_segv,g_old_abrt,g_old_bus,g_old_fpe,g_old_ill, andg_altstack_bufat file scope, andEventLoop::m_pipe_write_fd(src/event.cpp:16) is astatic volatile sig_atomic_t. Only oneTerminal/EventLoop/Appinstance should be active in a process at a time. - Mouse protocol:
EventLoopparses SGR 1006 mouse sequences ([<btn;col;rowMand[<btn;col;rowm,src/event.cpp:36-107). Legacy X10 ([M...) mouse sequences are not parsed byEventLoop. - Bracketed paste size cap:
EventLoopcaps buffered incomplete bracketed pastes ([200~) at4 * 1024 * 1024bytes (4 MB) or500ms of inactivity before flushing (src/event.cpp:645, 778). - Inline
Graphemecapacity:Grapheme::dataischar data[36], storing up to35UTF-8 bytes per cell (include/koto/utf8.hpp:28, 90). Clusters longer than 35 bytes are truncated at the last complete codepoint boundary that fits within 35 bytes.
Widget and focus limitations
Section titled “Widget and focus limitations”- Single SGR style per
Textwidget:koto::Textapplies a singlem_fg,m_bg, andm_attrsbitmask to all characters it draws (include/koto/text.hpp:57-58). To render multiple colors on the same line, split the line withLayout::horizontalor write cells directly toFrame. - No mouse-click cursor positioning inside
TextInputorTextArea: Left-clicking aTextInputorTextArearegistered inFocusManagerfocuses the widget, butTextInputStatehas nohandle_mousemethod andTextAreaState::handle_mouseonly handlesWheelUpandWheelDown(src/text_area.cpp:397-410). To move the caret on click, handleMouseEventinapp.on_mouse(...)usingvisual_col_to_byte_offset(). Key::TabinsideFocusManagervs.TextArea:FocusManager::handle_keyinterceptsKey::TabandKey::BackTabto cycle focus before invoking the active widget’shandle_key(src/focus.cpp:550-576). To insert 4 spaces withTabinside a focusedTextArea, register afm.interceptor(...)that forwardsKey::Tabtoeditor_state.handle_event(key)whenfm.is_focused(editor_state).
Frequently asked questions
Section titled “Frequently asked questions”Why does .id("my_name") fail to compile with an ambiguous overload error?
Section titled “Why does .id("my_name") fail to compile with an ambiguous overload error?”koto::Id defines both constexpr Id(const char* str) noexcept and Id(const void* ptr) noexcept (include/koto/id.hpp:64, 75). When passing a string literal to a method taking Id (such as .id(...)), both conversions are standard/user-defined pointer conversions of equal rank. Wrap the string literal in Id("my_name"):
Box().id(Id("my_name")).draw(frame, box_area);How do I wake the UI from a background worker thread?
Section titled “How do I wake the UI from a background worker thread?”Mutate shared state using atomic variables or a mutex, then call app.request_redraw() (include/koto/app.hpp:37). request_redraw() sets m_needs_draw = true and calls m_loop.wakeup(), which writes 1 byte ('W') to the non-blocking self-pipe to wake EventLoop::poll() immediately (src/app.cpp:78-82, src/event.cpp:828-835).
Why does my application not quit when I press Ctrl+C or q?
Section titled “Why does my application not quit when I press Ctrl+C or q?”Terminal::enter_raw_mode() disables ISIG (src/terminal.cpp:246), and App does not hardcode any exit keys. Register an app.on_key handler (or fm.interceptor) that calls app.quit().