Skip to content

Commit 620697d

Browse files
bugaevcawesomekling
authored andcommitted
LibVT: Move most of key press handling logic into VT::Terminal
This will let us share it between the userspace (TerminalWidget) and the Kernel.
1 parent fce49b3 commit 620697d

File tree

3 files changed

+88
-74
lines changed

3 files changed

+88
-74
lines changed

Libraries/LibVT/Terminal.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
*/
2626

2727
#include <AK/StringBuilder.h>
28+
#include <AK/StringView.h>
2829
#include <LibVT/Terminal.h>
2930
#include <string.h>
3031

@@ -1004,6 +1005,69 @@ void Terminal::emit_string(const StringView& string)
10041005
m_client.emit((const u8*)string.characters_without_null_termination(), string.length());
10051006
}
10061007

1008+
void Terminal::handle_key_press(KeyCode key, u8 character, u8 flags)
1009+
{
1010+
bool ctrl = flags & Mod_Ctrl;
1011+
bool alt = flags & Mod_Alt;
1012+
bool shift = flags & Mod_Shift;
1013+
1014+
switch (key) {
1015+
case KeyCode::Key_Up:
1016+
emit_string(ctrl ? "\033[OA" : "\033[A");
1017+
return;
1018+
case KeyCode::Key_Down:
1019+
emit_string(ctrl ? "\033[OB" : "\033[B");
1020+
return;
1021+
case KeyCode::Key_Right:
1022+
emit_string(ctrl ? "\033[OC" : "\033[C");
1023+
return;
1024+
case KeyCode::Key_Left:
1025+
emit_string(ctrl ? "\033[OD" : "\033[D");
1026+
return;
1027+
case KeyCode::Key_Insert:
1028+
emit_string("\033[2~");
1029+
return;
1030+
case KeyCode::Key_Delete:
1031+
emit_string("\033[3~");
1032+
return;
1033+
case KeyCode::Key_Home:
1034+
emit_string("\033[H");
1035+
return;
1036+
case KeyCode::Key_End:
1037+
emit_string("\033[F");
1038+
return;
1039+
case KeyCode::Key_PageUp:
1040+
emit_string("\033[5~");
1041+
return;
1042+
case KeyCode::Key_PageDown:
1043+
emit_string("\033[6~");
1044+
return;
1045+
default:
1046+
break;
1047+
}
1048+
1049+
if (shift && key == KeyCode::Key_Tab) {
1050+
emit_string("\033[Z");
1051+
return;
1052+
}
1053+
1054+
// Key event was not one of the above special cases,
1055+
// attempt to treat it as a character...
1056+
if (ctrl) {
1057+
if (character >= 'a' && character <= 'z') {
1058+
character = character - 'a' + 1;
1059+
} else if (character == '\\') {
1060+
character = 0x1c;
1061+
}
1062+
}
1063+
1064+
// Alt modifier sends escape prefix.
1065+
if (alt)
1066+
emit_string("\033");
1067+
1068+
emit_string({ &character, 1 });
1069+
}
1070+
10071071
void Terminal::unimplemented_escape()
10081072
{
10091073
StringBuilder builder;

Libraries/LibVT/Terminal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <AK/NonnullOwnPtrVector.h>
3131
#include <AK/String.h>
3232
#include <AK/Vector.h>
33+
#include <Kernel/KeyCode.h>
3334
#include <LibVT/Line.h>
3435
#include <LibVT/Position.h>
3536

@@ -95,6 +96,7 @@ class Terminal {
9596
const NonnullOwnPtrVector<Line>& history() const { return m_history; }
9697

9798
void inject_string(const StringView&);
99+
void handle_key_press(KeyCode, u8 charatcter, u8 flags);
98100

99101
Attribute attribute_at(const Position&) const;
100102

Libraries/LibVT/TerminalWidget.cpp

Lines changed: 22 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -206,90 +206,38 @@ void TerminalWidget::keydown_event(GUI::KeyEvent& event)
206206
m_cursor_blink_timer->stop();
207207
m_cursor_blink_state = true;
208208
m_cursor_blink_timer->start();
209-
auto ctrl_held = !!(event.modifiers() & Mod_Ctrl);
210209

211-
switch (event.key()) {
212-
case KeyCode::Key_Up:
213-
write(m_ptm_fd, ctrl_held ? "\033[OA" : "\033[A", 3 + ctrl_held);
214-
return;
215-
case KeyCode::Key_Down:
216-
write(m_ptm_fd, ctrl_held ? "\033[OB" : "\033[B", 3 + ctrl_held);
217-
return;
218-
case KeyCode::Key_Right:
219-
write(m_ptm_fd, ctrl_held ? "\033[OC" : "\033[C", 3 + ctrl_held);
220-
return;
221-
case KeyCode::Key_Left:
222-
write(m_ptm_fd, ctrl_held ? "\033[OD" : "\033[D", 3 + ctrl_held);
223-
return;
224-
case KeyCode::Key_Insert:
225-
write(m_ptm_fd, "\033[2~", 4);
210+
if (event.key() == KeyCode::Key_PageUp && event.modifiers() == Mod_Shift) {
211+
m_scrollbar->set_value(m_scrollbar->value() - m_terminal.rows());
226212
return;
227-
case KeyCode::Key_Delete:
228-
write(m_ptm_fd, "\033[3~", 4);
229-
return;
230-
case KeyCode::Key_Home:
231-
write(m_ptm_fd, "\033[H", 3);
232-
return;
233-
case KeyCode::Key_End:
234-
write(m_ptm_fd, "\033[F", 3);
235-
return;
236-
case KeyCode::Key_PageUp:
237-
if (event.modifiers() == Mod_Shift) {
238-
m_scrollbar->set_value(m_scrollbar->value() - m_terminal.rows());
239-
return;
240-
}
241-
write(m_ptm_fd, "\033[5~", 4);
242-
return;
243-
case KeyCode::Key_PageDown:
244-
if (event.modifiers() == Mod_Shift) {
245-
m_scrollbar->set_value(m_scrollbar->value() + m_terminal.rows());
246-
return;
247-
}
248-
write(m_ptm_fd, "\033[6~", 4);
249-
return;
250-
case KeyCode::Key_Alt:
251-
m_alt_key_held = true;
213+
}
214+
if (event.key() == KeyCode::Key_PageDown && event.modifiers() == Mod_Shift) {
215+
m_scrollbar->set_value(m_scrollbar->value() + m_terminal.rows());
252216
return;
253-
default:
254-
break;
255217
}
256-
257-
if (event.shift() && event.key() == KeyCode::Key_Tab) {
258-
write(m_ptm_fd, "\033[Z", 3);
218+
if (event.key() == KeyCode::Key_Alt) {
219+
m_alt_key_held = true;
259220
return;
260221
}
261222

262-
// Key event was not one of the above special cases,
263-
// attempt to treat it as a character...
264-
if (event.text().length() == 1) {
265-
// 1 byte input == ASCII
266-
char ch = !event.text().is_empty() ? event.text()[0] : 0;
267-
if (event.ctrl()) {
268-
if (ch >= 'a' && ch <= 'z') {
269-
ch = ch - 'a' + 1;
270-
} else if (ch == '\\') {
271-
ch = 0x1c;
272-
}
273-
}
274-
275-
// ALT modifier sends escape prefix
276-
if (event.alt())
277-
write(m_ptm_fd, "\033", 1);
278-
279-
//Clear the selection if we type in/behind it
280-
auto future_cursor_column = (event.key() == KeyCode::Key_Backspace) ? m_terminal.cursor_column() - 1 : m_terminal.cursor_column();
281-
auto min_selection_row = min(m_selection_start.row(), m_selection_end.row());
282-
auto max_selection_row = max(m_selection_start.row(), m_selection_end.row());
223+
// Clear the selection if we type in/behind it.
224+
auto future_cursor_column = (event.key() == KeyCode::Key_Backspace) ? m_terminal.cursor_column() - 1 : m_terminal.cursor_column();
225+
auto min_selection_row = min(m_selection_start.row(), m_selection_end.row());
226+
auto max_selection_row = max(m_selection_start.row(), m_selection_end.row());
283227

284-
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) {
285-
m_selection_end = {};
286-
update();
287-
}
228+
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) {
229+
m_selection_end = {};
230+
update();
231+
}
288232

289-
write(m_ptm_fd, &ch, 1);
290-
} else if (event.text().length() > 1) {
291-
// 2+ byte input == Unicode
233+
if (event.text().length() > 2) {
234+
// Unicode (likely emoji), just emit it.
292235
write(m_ptm_fd, event.text().characters(), event.text().length());
236+
} else {
237+
// Ask the terminal to generate the correct character sequence and send
238+
// it back to us via emit().
239+
u8 character = event.text().length() == 1 ? event.text()[0] : 0;
240+
m_terminal.handle_key_press(event.key(), character, event.modifiers());
293241
}
294242

295243
if (event.key() != Key_Control && event.key() != Key_Alt && event.key() != Key_Shift && event.key() != Key_Logo)

0 commit comments

Comments
 (0)