diff options
author | Sergey Bugaev <bugaevc@serenityos.org> | 2020-05-27 00:31:30 +0300 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-05-27 11:19:38 +0200 |
commit | 620697d924c15d62719ced9b4a2cab909bec74cb (patch) | |
tree | 2ff5fb4c1042726f7d674cb1605e3a7136f03cf8 /Libraries | |
parent | fce49b3e32f1813670b413a517ea670ee0a0a912 (diff) | |
download | serenity-620697d924c15d62719ced9b4a2cab909bec74cb.zip |
LibVT: Move most of key press handling logic into VT::Terminal
This will let us share it between the userspace (TerminalWidget) and the Kernel.
Diffstat (limited to 'Libraries')
-rw-r--r-- | Libraries/LibVT/Terminal.cpp | 64 | ||||
-rw-r--r-- | Libraries/LibVT/Terminal.h | 2 | ||||
-rw-r--r-- | Libraries/LibVT/TerminalWidget.cpp | 96 |
3 files changed, 88 insertions, 74 deletions
diff --git a/Libraries/LibVT/Terminal.cpp b/Libraries/LibVT/Terminal.cpp index 41567857fb..d35f64066e 100644 --- a/Libraries/LibVT/Terminal.cpp +++ b/Libraries/LibVT/Terminal.cpp @@ -25,6 +25,7 @@ */ #include <AK/StringBuilder.h> +#include <AK/StringView.h> #include <LibVT/Terminal.h> #include <string.h> @@ -1004,6 +1005,69 @@ void Terminal::emit_string(const StringView& string) m_client.emit((const u8*)string.characters_without_null_termination(), string.length()); } +void Terminal::handle_key_press(KeyCode key, u8 character, u8 flags) +{ + bool ctrl = flags & Mod_Ctrl; + bool alt = flags & Mod_Alt; + bool shift = flags & Mod_Shift; + + switch (key) { + case KeyCode::Key_Up: + emit_string(ctrl ? "\033[OA" : "\033[A"); + return; + case KeyCode::Key_Down: + emit_string(ctrl ? "\033[OB" : "\033[B"); + return; + case KeyCode::Key_Right: + emit_string(ctrl ? "\033[OC" : "\033[C"); + return; + case KeyCode::Key_Left: + emit_string(ctrl ? "\033[OD" : "\033[D"); + return; + case KeyCode::Key_Insert: + emit_string("\033[2~"); + return; + case KeyCode::Key_Delete: + emit_string("\033[3~"); + return; + case KeyCode::Key_Home: + emit_string("\033[H"); + return; + case KeyCode::Key_End: + emit_string("\033[F"); + return; + case KeyCode::Key_PageUp: + emit_string("\033[5~"); + return; + case KeyCode::Key_PageDown: + emit_string("\033[6~"); + return; + default: + break; + } + + if (shift && key == KeyCode::Key_Tab) { + emit_string("\033[Z"); + return; + } + + // Key event was not one of the above special cases, + // attempt to treat it as a character... + if (ctrl) { + if (character >= 'a' && character <= 'z') { + character = character - 'a' + 1; + } else if (character == '\\') { + character = 0x1c; + } + } + + // Alt modifier sends escape prefix. + if (alt) + emit_string("\033"); + + emit_string({ &character, 1 }); +} + void Terminal::unimplemented_escape() { StringBuilder builder; diff --git a/Libraries/LibVT/Terminal.h b/Libraries/LibVT/Terminal.h index d4061856df..4f8d10ad50 100644 --- a/Libraries/LibVT/Terminal.h +++ b/Libraries/LibVT/Terminal.h @@ -30,6 +30,7 @@ #include <AK/NonnullOwnPtrVector.h> #include <AK/String.h> #include <AK/Vector.h> +#include <Kernel/KeyCode.h> #include <LibVT/Line.h> #include <LibVT/Position.h> @@ -95,6 +96,7 @@ public: const NonnullOwnPtrVector<Line>& history() const { return m_history; } void inject_string(const StringView&); + void handle_key_press(KeyCode, u8 charatcter, u8 flags); Attribute attribute_at(const Position&) const; diff --git a/Libraries/LibVT/TerminalWidget.cpp b/Libraries/LibVT/TerminalWidget.cpp index 75b5949f02..aa381566ee 100644 --- a/Libraries/LibVT/TerminalWidget.cpp +++ b/Libraries/LibVT/TerminalWidget.cpp @@ -206,90 +206,38 @@ void TerminalWidget::keydown_event(GUI::KeyEvent& event) m_cursor_blink_timer->stop(); m_cursor_blink_state = true; m_cursor_blink_timer->start(); - auto ctrl_held = !!(event.modifiers() & Mod_Ctrl); - switch (event.key()) { - case KeyCode::Key_Up: - write(m_ptm_fd, ctrl_held ? "\033[OA" : "\033[A", 3 + ctrl_held); - return; - case KeyCode::Key_Down: - write(m_ptm_fd, ctrl_held ? "\033[OB" : "\033[B", 3 + ctrl_held); - return; - case KeyCode::Key_Right: - write(m_ptm_fd, ctrl_held ? "\033[OC" : "\033[C", 3 + ctrl_held); - return; - case KeyCode::Key_Left: - write(m_ptm_fd, ctrl_held ? "\033[OD" : "\033[D", 3 + ctrl_held); - return; - case KeyCode::Key_Insert: - write(m_ptm_fd, "\033[2~", 4); + if (event.key() == KeyCode::Key_PageUp && event.modifiers() == Mod_Shift) { + m_scrollbar->set_value(m_scrollbar->value() - m_terminal.rows()); return; - case KeyCode::Key_Delete: - write(m_ptm_fd, "\033[3~", 4); - return; - case KeyCode::Key_Home: - write(m_ptm_fd, "\033[H", 3); - return; - case KeyCode::Key_End: - write(m_ptm_fd, "\033[F", 3); - return; - case KeyCode::Key_PageUp: - if (event.modifiers() == Mod_Shift) { - m_scrollbar->set_value(m_scrollbar->value() - m_terminal.rows()); - return; - } - write(m_ptm_fd, "\033[5~", 4); - return; - case KeyCode::Key_PageDown: - if (event.modifiers() == Mod_Shift) { - m_scrollbar->set_value(m_scrollbar->value() + m_terminal.rows()); - return; - } - write(m_ptm_fd, "\033[6~", 4); - return; - case KeyCode::Key_Alt: - m_alt_key_held = true; + } + if (event.key() == KeyCode::Key_PageDown && event.modifiers() == Mod_Shift) { + m_scrollbar->set_value(m_scrollbar->value() + m_terminal.rows()); return; - default: - break; } - - if (event.shift() && event.key() == KeyCode::Key_Tab) { - write(m_ptm_fd, "\033[Z", 3); + if (event.key() == KeyCode::Key_Alt) { + m_alt_key_held = true; return; } - // Key event was not one of the above special cases, - // attempt to treat it as a character... - if (event.text().length() == 1) { - // 1 byte input == ASCII - char ch = !event.text().is_empty() ? event.text()[0] : 0; - if (event.ctrl()) { - if (ch >= 'a' && ch <= 'z') { - ch = ch - 'a' + 1; - } else if (ch == '\\') { - ch = 0x1c; - } - } - - // ALT modifier sends escape prefix - if (event.alt()) - write(m_ptm_fd, "\033", 1); - - //Clear the selection if we type in/behind it - auto future_cursor_column = (event.key() == KeyCode::Key_Backspace) ? m_terminal.cursor_column() - 1 : m_terminal.cursor_column(); - auto min_selection_row = min(m_selection_start.row(), m_selection_end.row()); - auto max_selection_row = max(m_selection_start.row(), m_selection_end.row()); + // Clear the selection if we type in/behind it. + auto future_cursor_column = (event.key() == KeyCode::Key_Backspace) ? m_terminal.cursor_column() - 1 : m_terminal.cursor_column(); + auto min_selection_row = min(m_selection_start.row(), m_selection_end.row()); + auto max_selection_row = max(m_selection_start.row(), m_selection_end.row()); - if (future_cursor_column <= last_selection_column_on_row(m_terminal.cursor_row()) && m_terminal.cursor_row() >= min_selection_row && m_terminal.cursor_row() <= max_selection_row) { - m_selection_end = {}; - update(); - } + if (future_cursor_column <= last_selection_column_on_row(m_terminal.cursor_row()) && m_terminal.cursor_row() >= min_selection_row && m_terminal.cursor_row() <= max_selection_row) { + m_selection_end = {}; + update(); + } - write(m_ptm_fd, &ch, 1); - } else if (event.text().length() > 1) { - // 2+ byte input == Unicode + if (event.text().length() > 2) { + // Unicode (likely emoji), just emit it. write(m_ptm_fd, event.text().characters(), event.text().length()); + } else { + // Ask the terminal to generate the correct character sequence and send + // it back to us via emit(). + u8 character = event.text().length() == 1 ? event.text()[0] : 0; + m_terminal.handle_key_press(event.key(), character, event.modifiers()); } if (event.key() != Key_Control && event.key() != Key_Alt && event.key() != Key_Shift && event.key() != Key_Logo) |